1 | // |
2 | // RWLock.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Threading |
6 | // Module: RWLock |
7 | // |
8 | // Definition of the RWLock class. |
9 | // |
10 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_RWLock_INCLUDED |
18 | #define Foundation_RWLock_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/Exception.h" |
23 | |
24 | |
25 | // TODO: std::shared_timed_mutex has separate read and write unlock |
26 | |
27 | //#define POCO_CXX11_RWLOCK_FINISHED |
28 | |
29 | |
30 | #if defined(POCO_CXX11_RWLOCK_FINISHED) && defined(POCO_ENABLE_CPP14) |
31 | #include "Poco/RWLock_STD.h" |
32 | #elif defined(POCO_OS_FAMILY_WINDOWS) |
33 | #if defined(_WIN32_WCE) |
34 | #include "Poco/RWLock_WINCE.h" |
35 | #else |
36 | #include "Poco/RWLock_WIN32.h" |
37 | #endif |
38 | #elif POCO_OS == POCO_OS_ANDROID |
39 | #include "Poco/RWLock_Android.h" |
40 | #elif defined(POCO_VXWORKS) |
41 | #include "Poco/RWLock_VX.h" |
42 | #else |
43 | #include "Poco/RWLock_POSIX.h" |
44 | #endif |
45 | |
46 | |
47 | namespace Poco { |
48 | |
49 | |
50 | class ScopedRWLock; |
51 | class ScopedReadRWLock; |
52 | class ScopedWriteRWLock; |
53 | |
54 | |
55 | class Foundation_API RWLock: private RWLockImpl |
56 | /// A reader writer lock allows multiple concurrent |
57 | /// readers or one exclusive writer. |
58 | { |
59 | public: |
60 | typedef ScopedRWLock ScopedLock; |
61 | typedef ScopedReadRWLock ScopedReadLock; |
62 | typedef ScopedWriteRWLock ScopedWriteLock; |
63 | |
64 | RWLock(); |
65 | /// Creates the Reader/Writer lock. |
66 | |
67 | ~RWLock(); |
68 | /// Destroys the Reader/Writer lock. |
69 | |
70 | void readLock(); |
71 | /// Acquires a read lock. If another thread currently holds a write lock, |
72 | /// waits until the write lock is released. |
73 | |
74 | bool tryReadLock(); |
75 | /// Tries to acquire a read lock. Immediately returns true if successful, or |
76 | /// false if another thread currently holds a write lock. |
77 | |
78 | void writeLock(); |
79 | /// Acquires a write lock. If one or more other threads currently hold |
80 | /// locks, waits until all locks are released. The results are undefined |
81 | /// if the same thread already holds a read or write lock |
82 | |
83 | bool tryWriteLock(); |
84 | /// Tries to acquire a write lock. Immediately returns true if successful, |
85 | /// or false if one or more other threads currently hold |
86 | /// locks. The result is undefined if the same thread already |
87 | /// holds a read or write lock. |
88 | |
89 | void unlock(); |
90 | /// Releases the read or write lock. |
91 | |
92 | private: |
93 | RWLock(const RWLock&); |
94 | RWLock& operator = (const RWLock&); |
95 | }; |
96 | |
97 | |
98 | class Foundation_API ScopedRWLock |
99 | /// A variant of ScopedLock for reader/writer locks. |
100 | { |
101 | public: |
102 | ScopedRWLock(RWLock& rwl, bool write = false); |
103 | ~ScopedRWLock(); |
104 | |
105 | private: |
106 | RWLock& _rwl; |
107 | |
108 | ScopedRWLock(); |
109 | ScopedRWLock(const ScopedRWLock&); |
110 | ScopedRWLock& operator = (const ScopedRWLock&); |
111 | }; |
112 | |
113 | |
114 | class Foundation_API ScopedReadRWLock : public ScopedRWLock |
115 | /// A variant of ScopedLock for reader locks. |
116 | { |
117 | public: |
118 | ScopedReadRWLock(RWLock& rwl); |
119 | ~ScopedReadRWLock(); |
120 | }; |
121 | |
122 | |
123 | class Foundation_API ScopedWriteRWLock : public ScopedRWLock |
124 | /// A variant of ScopedLock for writer locks. |
125 | { |
126 | public: |
127 | ScopedWriteRWLock(RWLock& rwl); |
128 | ~ScopedWriteRWLock(); |
129 | }; |
130 | |
131 | |
132 | // |
133 | // inlines |
134 | // |
135 | inline void RWLock::readLock() |
136 | { |
137 | readLockImpl(); |
138 | } |
139 | |
140 | |
141 | inline bool RWLock::tryReadLock() |
142 | { |
143 | return tryReadLockImpl(); |
144 | } |
145 | |
146 | |
147 | inline void RWLock::writeLock() |
148 | { |
149 | writeLockImpl(); |
150 | } |
151 | |
152 | |
153 | inline bool RWLock::tryWriteLock() |
154 | { |
155 | return tryWriteLockImpl(); |
156 | } |
157 | |
158 | |
159 | inline void RWLock::unlock() |
160 | { |
161 | unlockImpl(); |
162 | } |
163 | |
164 | |
165 | inline ScopedRWLock::ScopedRWLock(RWLock& rwl, bool write): _rwl(rwl) |
166 | { |
167 | if (write) |
168 | _rwl.writeLock(); |
169 | else |
170 | _rwl.readLock(); |
171 | } |
172 | |
173 | |
174 | inline ScopedRWLock::~ScopedRWLock() |
175 | { |
176 | try |
177 | { |
178 | _rwl.unlock(); |
179 | } |
180 | catch (...) |
181 | { |
182 | poco_unexpected(); |
183 | } |
184 | } |
185 | |
186 | |
187 | inline ScopedReadRWLock::ScopedReadRWLock(RWLock& rwl): ScopedRWLock(rwl, false) |
188 | { |
189 | } |
190 | |
191 | |
192 | inline ScopedReadRWLock::~ScopedReadRWLock() |
193 | { |
194 | } |
195 | |
196 | |
197 | inline ScopedWriteRWLock::ScopedWriteRWLock(RWLock& rwl): ScopedRWLock(rwl, true) |
198 | { |
199 | } |
200 | |
201 | |
202 | inline ScopedWriteRWLock::~ScopedWriteRWLock() |
203 | { |
204 | } |
205 | |
206 | |
207 | } // namespace Poco |
208 | |
209 | |
210 | #endif // Foundation_RWLock_INCLUDED |
211 | |