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
17namespace 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