1 | // LAF Base Library |
2 | // Copyright (C) 2020-2022 Igara Studio S.A. |
3 | // Copyright (C) 2001-2016 David Capello |
4 | // |
5 | // This file is released under the terms of the MIT license. |
6 | // Read LICENSE.txt for more information. |
7 | |
8 | #ifndef BASE_RW_LOCK_H_INCLUDED |
9 | #define BASE_RW_LOCK_H_INCLUDED |
10 | #pragma once |
11 | |
12 | #include "base/disable_copying.h" |
13 | |
14 | #include <atomic> |
15 | #include <mutex> |
16 | |
17 | namespace base { |
18 | |
19 | // A readers-writer lock implementation |
20 | class RWLock { |
21 | public: |
22 | enum LockType { |
23 | ReadLock, |
24 | WriteLock |
25 | }; |
26 | |
27 | enum WeakLock { |
28 | WeakUnlocked, |
29 | WeakUnlocking, |
30 | WeakLocked, |
31 | }; |
32 | |
33 | RWLock(); |
34 | ~RWLock(); |
35 | |
36 | // Returns true if we can lock this object for writting purposes |
37 | // in case that the current thread has it locked for reading. |
38 | bool canWriteLockFromRead() const; |
39 | |
40 | // Locks the object to read or write on it, returning true if the |
41 | // object can be accessed in the desired mode. |
42 | bool lock(LockType lockType, int timeout); |
43 | |
44 | // If you've locked the object to read, using this method you can |
45 | // raise your access level to write it. |
46 | bool upgradeToWrite(int timeout); |
47 | |
48 | // If we've locked the object to write, using this method we can |
49 | // lower our access to read-only. |
50 | void downgradeToRead(); |
51 | |
52 | // Unlocks a previously successfully lock() operation. |
53 | void unlock(); |
54 | |
55 | // Tries to lock the object for read access in a "weak way" so |
56 | // other thread (e.g. UI thread) can lock the object removing this |
57 | // weak lock. |
58 | // |
59 | // The "weak_lock_flag" is used to notify when the "weak lock" is |
60 | // lost. |
61 | bool weakLock(std::atomic<WeakLock>* weak_lock_flag); |
62 | void weakUnlock(); |
63 | |
64 | private: |
65 | // Mutex to modify the 'locked' flag. |
66 | mutable std::mutex m_mutex; |
67 | |
68 | // True if some thread is writing the object. |
69 | bool m_write_lock; |
70 | |
71 | // Greater than zero when one or more threads are reading the object. |
72 | int m_read_locks; |
73 | |
74 | // If this isn' nullptr, it means that it points to an unique |
75 | // "weak" lock that can be unlocked from other thread. E.g. the |
76 | // backup/data recovery thread might weakly lock the object so if |
77 | // the user UI thread needs the object again, the backup process |
78 | // can stop. |
79 | std::atomic<WeakLock>* m_weak_lock; |
80 | |
81 | DISABLE_COPYING(RWLock); |
82 | }; |
83 | |
84 | } // namespace base |
85 | |
86 | #endif |
87 | |