blob: 3daf74d26c740dc3132e275654df2e0d870ee93a [file] [log] [blame]
Howard Hinnant6185ace2013-09-21 01:49:28 +00001// -*- C++ -*-
2//===------------------------ shared_mutex --------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_SHARED_MUTEX
12#define _LIBCPP_SHARED_MUTEX
13
14/*
15 shared_mutex synopsis
16
17// C++1y
18
19namespace std
20{
21
Marshall Clowac28c3d2015-06-30 14:04:14 +000022class shared_mutex // C++17
23{
24public:
25 shared_mutex();
26 ~shared_mutex();
27
28 shared_mutex(const shared_mutex&) = delete;
29 shared_mutex& operator=(const shared_mutex&) = delete;
30
31 // Exclusive ownership
32 void lock(); // blocking
33 bool try_lock();
34 void unlock();
35
36 // Shared ownership
37 void lock_shared(); // blocking
38 bool try_lock_shared();
39 void unlock_shared();
40
41 typedef implementation-defined native_handle_type; // See 30.2.3
42 native_handle_type native_handle(); // See 30.2.3
43};
44
David Majnemer10c8c362014-03-17 20:19:44 +000045class shared_timed_mutex
Howard Hinnant6185ace2013-09-21 01:49:28 +000046{
47public:
David Majnemer10c8c362014-03-17 20:19:44 +000048 shared_timed_mutex();
49 ~shared_timed_mutex();
Howard Hinnant6185ace2013-09-21 01:49:28 +000050
David Majnemer10c8c362014-03-17 20:19:44 +000051 shared_timed_mutex(const shared_timed_mutex&) = delete;
52 shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
Howard Hinnant6185ace2013-09-21 01:49:28 +000053
54 // Exclusive ownership
55 void lock(); // blocking
56 bool try_lock();
57 template <class Rep, class Period>
58 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
59 template <class Clock, class Duration>
60 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
61 void unlock();
62
63 // Shared ownership
64 void lock_shared(); // blocking
65 bool try_lock_shared();
66 template <class Rep, class Period>
67 bool
68 try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
69 template <class Clock, class Duration>
70 bool
71 try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
72 void unlock_shared();
73};
74
75template <class Mutex>
76class shared_lock
77{
78public:
79 typedef Mutex mutex_type;
80
81 // Shared locking
82 shared_lock() noexcept;
83 explicit shared_lock(mutex_type& m); // blocking
84 shared_lock(mutex_type& m, defer_lock_t) noexcept;
85 shared_lock(mutex_type& m, try_to_lock_t);
86 shared_lock(mutex_type& m, adopt_lock_t);
87 template <class Clock, class Duration>
88 shared_lock(mutex_type& m,
89 const chrono::time_point<Clock, Duration>& abs_time);
90 template <class Rep, class Period>
91 shared_lock(mutex_type& m,
92 const chrono::duration<Rep, Period>& rel_time);
93 ~shared_lock();
94
95 shared_lock(shared_lock const&) = delete;
96 shared_lock& operator=(shared_lock const&) = delete;
97
98 shared_lock(shared_lock&& u) noexcept;
99 shared_lock& operator=(shared_lock&& u) noexcept;
100
101 void lock(); // blocking
102 bool try_lock();
103 template <class Rep, class Period>
104 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
105 template <class Clock, class Duration>
106 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
107 void unlock();
108
109 // Setters
110 void swap(shared_lock& u) noexcept;
111 mutex_type* release() noexcept;
112
113 // Getters
114 bool owns_lock() const noexcept;
115 explicit operator bool () const noexcept;
116 mutex_type* mutex() const noexcept;
117};
118
119template <class Mutex>
120 void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
121
122} // std
123
124*/
125
126#include <__config>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000127#include <version>
Howard Hinnant6185ace2013-09-21 01:49:28 +0000128
Eric Fiselierf4433a32017-05-31 22:07:49 +0000129_LIBCPP_PUSH_MACROS
130#include <__undef_macros>
131
132
Louis Dionne5e0eadd2018-08-01 02:08:59 +0000133#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_LIBRARY)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000134
135#include <__mutex_base>
136
Howard Hinnant6185ace2013-09-21 01:49:28 +0000137#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
138#pragma GCC system_header
139#endif
140
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000141#ifdef _LIBCPP_HAS_NO_THREADS
142#error <shared_mutex> is not supported on this single threaded system
143#else // !_LIBCPP_HAS_NO_THREADS
144
Howard Hinnant6185ace2013-09-21 01:49:28 +0000145_LIBCPP_BEGIN_NAMESPACE_STD
146
Petr Hosek23e8a762018-11-09 23:32:25 +0000147struct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("shared_mutex"))
148__shared_mutex_base
Howard Hinnant6185ace2013-09-21 01:49:28 +0000149{
150 mutex __mut_;
151 condition_variable __gate1_;
152 condition_variable __gate2_;
153 unsigned __state_;
154
155 static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
156 static const unsigned __n_readers_ = ~__write_entered_;
Marshall Clowac28c3d2015-06-30 14:04:14 +0000157
158 __shared_mutex_base();
159 _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default;
160
161 __shared_mutex_base(const __shared_mutex_base&) = delete;
162 __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
163
164 // Exclusive ownership
Petr Hosek23e8a762018-11-09 23:32:25 +0000165 void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); // blocking
166 bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
167 void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
Marshall Clowac28c3d2015-06-30 14:04:14 +0000168
169 // Shared ownership
Petr Hosek23e8a762018-11-09 23:32:25 +0000170 void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_shared_capability()); // blocking
171 bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_shared_capability(true));
172 void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_shared_capability());
Marshall Clowac28c3d2015-06-30 14:04:14 +0000173
174// typedef implementation-defined native_handle_type; // See 30.2.3
175// native_handle_type native_handle(); // See 30.2.3
176};
177
178
179#if _LIBCPP_STD_VER > 14
Mehdi Amini228053d2017-05-04 17:08:54 +0000180class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex
Marshall Clowac28c3d2015-06-30 14:04:14 +0000181{
Marshall Clow580b6e62017-03-24 03:40:36 +0000182 __shared_mutex_base __base;
Marshall Clowac28c3d2015-06-30 14:04:14 +0000183public:
Eric Fiselier26654172017-05-08 01:31:50 +0000184 _LIBCPP_INLINE_VISIBILITY shared_mutex() : __base() {}
Marshall Clowac28c3d2015-06-30 14:04:14 +0000185 _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
186
187 shared_mutex(const shared_mutex&) = delete;
188 shared_mutex& operator=(const shared_mutex&) = delete;
189
190 // Exclusive ownership
191 _LIBCPP_INLINE_VISIBILITY void lock() { return __base.lock(); }
192 _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
193 _LIBCPP_INLINE_VISIBILITY void unlock() { return __base.unlock(); }
194
195 // Shared ownership
196 _LIBCPP_INLINE_VISIBILITY void lock_shared() { return __base.lock_shared(); }
197 _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
198 _LIBCPP_INLINE_VISIBILITY void unlock_shared() { return __base.unlock_shared(); }
199
200// typedef __shared_mutex_base::native_handle_type native_handle_type;
201// _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }
202};
203#endif
204
205
Mehdi Amini228053d2017-05-04 17:08:54 +0000206class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex
Marshall Clowac28c3d2015-06-30 14:04:14 +0000207{
Marshall Clow580b6e62017-03-24 03:40:36 +0000208 __shared_mutex_base __base;
Howard Hinnant6185ace2013-09-21 01:49:28 +0000209public:
David Majnemer10c8c362014-03-17 20:19:44 +0000210 shared_timed_mutex();
211 _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
Howard Hinnant6185ace2013-09-21 01:49:28 +0000212
David Majnemer10c8c362014-03-17 20:19:44 +0000213 shared_timed_mutex(const shared_timed_mutex&) = delete;
214 shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
Howard Hinnant6185ace2013-09-21 01:49:28 +0000215
216 // Exclusive ownership
217 void lock();
218 bool try_lock();
219 template <class _Rep, class _Period>
220 _LIBCPP_INLINE_VISIBILITY
221 bool
222 try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
223 {
224 return try_lock_until(chrono::steady_clock::now() + __rel_time);
225 }
226 template <class _Clock, class _Duration>
Shoaib Meenai55f3a462017-03-02 03:22:18 +0000227 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
Howard Hinnant6185ace2013-09-21 01:49:28 +0000228 bool
229 try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
230 void unlock();
231
232 // Shared ownership
233 void lock_shared();
234 bool try_lock_shared();
235 template <class _Rep, class _Period>
236 _LIBCPP_INLINE_VISIBILITY
237 bool
238 try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
239 {
240 return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
241 }
242 template <class _Clock, class _Duration>
Shoaib Meenai55f3a462017-03-02 03:22:18 +0000243 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
Howard Hinnant6185ace2013-09-21 01:49:28 +0000244 bool
245 try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
246 void unlock_shared();
247};
248
249template <class _Clock, class _Duration>
250bool
David Majnemer10c8c362014-03-17 20:19:44 +0000251shared_timed_mutex::try_lock_until(
Howard Hinnant6185ace2013-09-21 01:49:28 +0000252 const chrono::time_point<_Clock, _Duration>& __abs_time)
253{
Marshall Clowac28c3d2015-06-30 14:04:14 +0000254 unique_lock<mutex> __lk(__base.__mut_);
255 if (__base.__state_ & __base.__write_entered_)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000256 {
257 while (true)
258 {
Marshall Clowac28c3d2015-06-30 14:04:14 +0000259 cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);
260 if ((__base.__state_ & __base.__write_entered_) == 0)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000261 break;
262 if (__status == cv_status::timeout)
263 return false;
264 }
265 }
Marshall Clowac28c3d2015-06-30 14:04:14 +0000266 __base.__state_ |= __base.__write_entered_;
267 if (__base.__state_ & __base.__n_readers_)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000268 {
269 while (true)
270 {
Marshall Clowac28c3d2015-06-30 14:04:14 +0000271 cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);
272 if ((__base.__state_ & __base.__n_readers_) == 0)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000273 break;
274 if (__status == cv_status::timeout)
275 {
Marshall Clowac28c3d2015-06-30 14:04:14 +0000276 __base.__state_ &= ~__base.__write_entered_;
277 __base.__gate1_.notify_all();
Howard Hinnant6185ace2013-09-21 01:49:28 +0000278 return false;
279 }
280 }
281 }
282 return true;
283}
284
285template <class _Clock, class _Duration>
286bool
David Majnemer10c8c362014-03-17 20:19:44 +0000287shared_timed_mutex::try_lock_shared_until(
Howard Hinnant6185ace2013-09-21 01:49:28 +0000288 const chrono::time_point<_Clock, _Duration>& __abs_time)
289{
Marshall Clowac28c3d2015-06-30 14:04:14 +0000290 unique_lock<mutex> __lk(__base.__mut_);
291 if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000292 {
293 while (true)
294 {
Marshall Clowac28c3d2015-06-30 14:04:14 +0000295 cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);
296 if ((__base.__state_ & __base.__write_entered_) == 0 &&
297 (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000298 break;
299 if (status == cv_status::timeout)
300 return false;
301 }
302 }
Marshall Clowac28c3d2015-06-30 14:04:14 +0000303 unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;
304 __base.__state_ &= ~__base.__n_readers_;
305 __base.__state_ |= __num_readers;
Howard Hinnant6185ace2013-09-21 01:49:28 +0000306 return true;
307}
308
309template <class _Mutex>
310class shared_lock
311{
312public:
313 typedef _Mutex mutex_type;
314
315private:
316 mutex_type* __m_;
317 bool __owns_;
318
319public:
320 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000321 shared_lock() _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000322 : __m_(nullptr),
323 __owns_(false)
324 {}
325
326 _LIBCPP_INLINE_VISIBILITY
327 explicit shared_lock(mutex_type& __m)
Marshall Clow24ddc252016-04-13 17:02:23 +0000328 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000329 __owns_(true)
330 {__m_->lock_shared();}
331
332 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000333 shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
Marshall Clow24ddc252016-04-13 17:02:23 +0000334 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000335 __owns_(false)
336 {}
337
338 _LIBCPP_INLINE_VISIBILITY
339 shared_lock(mutex_type& __m, try_to_lock_t)
Marshall Clow24ddc252016-04-13 17:02:23 +0000340 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000341 __owns_(__m.try_lock_shared())
342 {}
343
344 _LIBCPP_INLINE_VISIBILITY
345 shared_lock(mutex_type& __m, adopt_lock_t)
Marshall Clow24ddc252016-04-13 17:02:23 +0000346 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000347 __owns_(true)
348 {}
349
350 template <class _Clock, class _Duration>
351 _LIBCPP_INLINE_VISIBILITY
352 shared_lock(mutex_type& __m,
353 const chrono::time_point<_Clock, _Duration>& __abs_time)
Marshall Clow24ddc252016-04-13 17:02:23 +0000354 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000355 __owns_(__m.try_lock_shared_until(__abs_time))
356 {}
357
358 template <class _Rep, class _Period>
359 _LIBCPP_INLINE_VISIBILITY
360 shared_lock(mutex_type& __m,
361 const chrono::duration<_Rep, _Period>& __rel_time)
Marshall Clow24ddc252016-04-13 17:02:23 +0000362 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000363 __owns_(__m.try_lock_shared_for(__rel_time))
364 {}
365
366 _LIBCPP_INLINE_VISIBILITY
367 ~shared_lock()
368 {
369 if (__owns_)
370 __m_->unlock_shared();
371 }
372
373 shared_lock(shared_lock const&) = delete;
374 shared_lock& operator=(shared_lock const&) = delete;
375
376 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000377 shared_lock(shared_lock&& __u) _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000378 : __m_(__u.__m_),
379 __owns_(__u.__owns_)
380 {
381 __u.__m_ = nullptr;
382 __u.__owns_ = false;
383 }
384
385 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000386 shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000387 {
388 if (__owns_)
389 __m_->unlock_shared();
390 __m_ = nullptr;
391 __owns_ = false;
392 __m_ = __u.__m_;
393 __owns_ = __u.__owns_;
394 __u.__m_ = nullptr;
395 __u.__owns_ = false;
396 return *this;
397 }
398
399 void lock();
400 bool try_lock();
401 template <class Rep, class Period>
402 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
403 template <class Clock, class Duration>
404 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
405 void unlock();
406
407 // Setters
408 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000409 void swap(shared_lock& __u) _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000410 {
411 _VSTD::swap(__m_, __u.__m_);
412 _VSTD::swap(__owns_, __u.__owns_);
413 }
414
415 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000416 mutex_type* release() _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000417 {
418 mutex_type* __m = __m_;
419 __m_ = nullptr;
420 __owns_ = false;
421 return __m;
422 }
423
424 // Getters
425 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000426 bool owns_lock() const _NOEXCEPT {return __owns_;}
Howard Hinnant6185ace2013-09-21 01:49:28 +0000427
428 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000429 explicit operator bool () const _NOEXCEPT {return __owns_;}
Howard Hinnant6185ace2013-09-21 01:49:28 +0000430
431 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000432 mutex_type* mutex() const _NOEXCEPT {return __m_;}
Howard Hinnant6185ace2013-09-21 01:49:28 +0000433};
434
435template <class _Mutex>
436void
437shared_lock<_Mutex>::lock()
438{
439 if (__m_ == nullptr)
440 __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
441 if (__owns_)
442 __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
443 __m_->lock_shared();
444 __owns_ = true;
445}
446
447template <class _Mutex>
448bool
449shared_lock<_Mutex>::try_lock()
450{
451 if (__m_ == nullptr)
452 __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
453 if (__owns_)
454 __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
455 __owns_ = __m_->try_lock_shared();
456 return __owns_;
457}
458
459template <class _Mutex>
460template <class _Rep, class _Period>
461bool
462shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
463{
464 if (__m_ == nullptr)
465 __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
466 if (__owns_)
467 __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
468 __owns_ = __m_->try_lock_shared_for(__d);
469 return __owns_;
470}
471
472template <class _Mutex>
473template <class _Clock, class _Duration>
474bool
475shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
476{
477 if (__m_ == nullptr)
478 __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
479 if (__owns_)
480 __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
481 __owns_ = __m_->try_lock_shared_until(__t);
482 return __owns_;
483}
484
485template <class _Mutex>
486void
487shared_lock<_Mutex>::unlock()
488{
489 if (!__owns_)
490 __throw_system_error(EPERM, "shared_lock::unlock: not locked");
491 __m_->unlock_shared();
492 __owns_ = false;
493}
494
495template <class _Mutex>
496inline _LIBCPP_INLINE_VISIBILITY
497void
Marshall Clowdf4053a2014-08-25 14:53:16 +0000498swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000499 {__x.swap(__y);}
500
501_LIBCPP_END_NAMESPACE_STD
502
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000503#endif // !_LIBCPP_HAS_NO_THREADS
504
Howard Hinnant6185ace2013-09-21 01:49:28 +0000505#endif // _LIBCPP_STD_VER > 11
506
Eric Fiselierf4433a32017-05-31 22:07:49 +0000507_LIBCPP_POP_MACROS
508
Howard Hinnant6185ace2013-09-21 01:49:28 +0000509#endif // _LIBCPP_SHARED_MUTEX