1 | // |
2 | // Mutex.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Threading |
6 | // Module: Mutex |
7 | // |
8 | // Definition of the Mutex and FastMutex classes. |
9 | // |
10 | // Copyright (c) 2004-2008, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_Mutex_INCLUDED |
18 | #define Foundation_Mutex_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/Exception.h" |
23 | #include "Poco/ScopedLock.h" |
24 | |
25 | #if (POCO_OS == POCO_OS_CYGWIN || defined(POCO_ANDROID)) |
26 | #include "Poco/Mutex_POSIX.h" |
27 | #else |
28 | #include "Poco/Mutex_STD.h" |
29 | #endif |
30 | |
31 | namespace Poco { |
32 | |
33 | |
34 | class Foundation_API Mutex: private MutexImpl |
35 | /// A Mutex (mutual exclusion) is a synchronization |
36 | /// mechanism used to control access to a shared resource |
37 | /// in a concurrent (multithreaded) scenario. |
38 | /// Using the ScopedLock class is the preferred way to automatically |
39 | /// lock and unlock a mutex. |
40 | { |
41 | public: |
42 | enum MutexType |
43 | /// The type of a mutex. |
44 | { |
45 | MUTEX_RECURSIVE = MUTEX_RECURSIVE_IMPL, /// A recursive mutex |
46 | MUTEX_NONRECURSIVE = MUTEX_NONRECURSIVE_IMPL /// A non-recursive mutex |
47 | }; |
48 | |
49 | typedef Poco::ScopedLock<Mutex> ScopedLock; |
50 | |
51 | explicit Mutex(MutexType type = MUTEX_RECURSIVE); |
52 | /// Creates the Mutex. |
53 | |
54 | ~Mutex(); |
55 | /// Destroys the Mutex. |
56 | |
57 | void lock(); |
58 | /// Locks the mutex. Blocks if the mutex |
59 | /// is held by another thread. |
60 | |
61 | void lock(long milliseconds); |
62 | /// Locks the mutex. Blocks up to the given number of milliseconds |
63 | /// if the mutex is held by another thread. Throws a TimeoutException |
64 | /// if the mutex can not be locked within the given timeout. |
65 | /// |
66 | /// Performance Note: On most platforms (including Windows), this member function is |
67 | /// implemented using a loop calling (the equivalent of) tryLock() and Thread::sleep(). |
68 | /// On POSIX platforms that support pthread_mutex_timedlock(), this is used. |
69 | |
70 | bool tryLock(); |
71 | /// Tries to lock the mutex. Returns false immediately |
72 | /// if the mutex is already held by another thread. |
73 | /// Returns true if the mutex was successfully locked. |
74 | |
75 | bool tryLock(long milliseconds); |
76 | /// Locks the mutex. Blocks up to the given number of milliseconds |
77 | /// if the mutex is held by another thread. |
78 | /// Returns true if the mutex was successfully locked. |
79 | /// |
80 | /// Performance Note: On most platforms (including Windows), this member function is |
81 | /// implemented using a loop calling (the equivalent of) tryLock() and Thread::sleep(). |
82 | /// On POSIX platforms that support pthread_mutex_timedlock(), this is used. |
83 | |
84 | void unlock(); |
85 | /// Unlocks the mutex so that it can be acquired by |
86 | /// other threads. |
87 | |
88 | private: |
89 | Mutex(const Mutex&); |
90 | Mutex& operator = (const Mutex&); |
91 | }; |
92 | |
93 | |
94 | class Foundation_API FastMutex: private FastMutexImpl |
95 | /// A FastMutex (mutual exclusion) is similar to a Mutex. |
96 | /// Locking a FastMutex is guaranteed to be at least as |
97 | /// fast as locking a Mutex. However, a FastMutex is not |
98 | /// guaranteed to be either recursive or non-recursive. |
99 | /// It is best suited to thread safe components like pools, |
100 | /// caches and queues where locking is internal to the component. |
101 | /// Using the ScopedLock class is the preferred way to automatically |
102 | /// lock and unlock a mutex. |
103 | { |
104 | public: |
105 | typedef Poco::ScopedLock<FastMutex> ScopedLock; |
106 | |
107 | FastMutex(); |
108 | /// creates the Mutex. |
109 | |
110 | ~FastMutex(); |
111 | /// destroys the Mutex. |
112 | |
113 | void lock(); |
114 | /// Locks the mutex. Blocks if the mutex |
115 | /// is held by another thread. |
116 | |
117 | void lock(long milliseconds); |
118 | /// Locks the mutex. Blocks up to the given number of milliseconds |
119 | /// if the mutex is held by another thread. Throws a TimeoutException |
120 | /// if the mutex can not be locked within the given timeout. |
121 | /// |
122 | /// Performance Note: On most platforms (including Windows), this member function is |
123 | /// implemented using a loop calling (the equivalent of) tryLock() and Thread::sleep(). |
124 | /// On POSIX platforms that support pthread_mutex_timedlock(), this is used. |
125 | |
126 | bool tryLock(); |
127 | /// Tries to lock the mutex. Returns false immediately |
128 | /// if the mutex is already held by another thread. |
129 | /// Returns true if the mutex was successfully locked. |
130 | |
131 | bool tryLock(long milliseconds); |
132 | /// Locks the mutex. Blocks up to the given number of milliseconds |
133 | /// if the mutex is held by another thread. |
134 | /// Returns true if the mutex was successfully locked. |
135 | /// |
136 | /// Performance Note: On most platforms (including Windows), this member function is |
137 | /// implemented using a loop calling (the equivalent of) tryLock() and Thread::sleep(). |
138 | /// On POSIX platforms that support pthread_mutex_timedlock(), this is used. |
139 | |
140 | void unlock(); |
141 | /// Unlocks the mutex so that it can be acquired by |
142 | /// other threads. |
143 | |
144 | private: |
145 | FastMutex(const FastMutex&); |
146 | FastMutex& operator = (const FastMutex&); |
147 | }; |
148 | |
149 | |
150 | class Foundation_API NullMutex |
151 | /// A NullMutex is an empty mutex implementation |
152 | /// which performs no locking at all. Useful in policy driven design |
153 | /// where the type of mutex used can be now a template parameter allowing the user to switch |
154 | /// between thread-safe and not thread-safe depending on his need |
155 | /// Works with the ScopedLock class |
156 | { |
157 | public: |
158 | typedef Poco::ScopedLock<NullMutex> ScopedLock; |
159 | |
160 | NullMutex() |
161 | /// Creates the NullMutex. |
162 | { |
163 | } |
164 | |
165 | ~NullMutex() |
166 | /// Destroys the NullMutex. |
167 | { |
168 | } |
169 | |
170 | void lock() |
171 | /// Does nothing. |
172 | { |
173 | } |
174 | |
175 | void lock(long) |
176 | /// Does nothing. |
177 | { |
178 | } |
179 | |
180 | bool tryLock() |
181 | /// Does nothing and always returns true. |
182 | { |
183 | return true; |
184 | } |
185 | |
186 | bool tryLock(long) |
187 | /// Does nothing and always returns true. |
188 | { |
189 | return true; |
190 | } |
191 | |
192 | void unlock() |
193 | /// Does nothing. |
194 | { |
195 | } |
196 | }; |
197 | |
198 | |
199 | // |
200 | // inlines |
201 | // |
202 | inline void Mutex::lock() |
203 | { |
204 | lockImpl(); |
205 | } |
206 | |
207 | |
208 | inline void Mutex::lock(long milliseconds) |
209 | { |
210 | if (!tryLockImpl(milliseconds)) |
211 | throw TimeoutException(); |
212 | } |
213 | |
214 | |
215 | inline bool Mutex::tryLock() |
216 | { |
217 | return tryLockImpl(); |
218 | } |
219 | |
220 | |
221 | inline bool Mutex::tryLock(long milliseconds) |
222 | { |
223 | return tryLockImpl(milliseconds); |
224 | } |
225 | |
226 | |
227 | inline void Mutex::unlock() |
228 | { |
229 | unlockImpl(); |
230 | } |
231 | |
232 | |
233 | inline void FastMutex::lock() |
234 | { |
235 | lockImpl(); |
236 | } |
237 | |
238 | |
239 | inline void FastMutex::lock(long milliseconds) |
240 | { |
241 | if (!tryLockImpl(milliseconds)) |
242 | throw TimeoutException(); |
243 | } |
244 | |
245 | |
246 | inline bool FastMutex::tryLock() |
247 | { |
248 | return tryLockImpl(); |
249 | } |
250 | |
251 | |
252 | inline bool FastMutex::tryLock(long milliseconds) |
253 | { |
254 | return tryLockImpl(milliseconds); |
255 | } |
256 | |
257 | |
258 | inline void FastMutex::unlock() |
259 | { |
260 | unlockImpl(); |
261 | } |
262 | |
263 | |
264 | } // namespace Poco |
265 | |
266 | |
267 | #endif // Foundation_Mutex_INCLUDED |
268 | |