blob: e918e1bdf604cea9d8eb7fb0227e641ae652c898 [file] [log] [blame]
Howard Hinnant6185ace2013-09-21 01:49:28 +00001//===---------------------- shared_mutex.cpp ------------------------------===//
2//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnant6185ace2013-09-21 01:49:28 +00006//
7//===----------------------------------------------------------------------===//
8
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +00009#include "__config"
10#ifndef _LIBCPP_HAS_NO_THREADS
11
Howard Hinnant6185ace2013-09-21 01:49:28 +000012#include "shared_mutex"
13
14_LIBCPP_BEGIN_NAMESPACE_STD
15
Marshall Clowac28c3d2015-06-30 14:04:14 +000016// Shared Mutex Base
17__shared_mutex_base::__shared_mutex_base()
Howard Hinnant6185ace2013-09-21 01:49:28 +000018 : __state_(0)
19{
20}
21
22// Exclusive ownership
23
24void
Marshall Clowac28c3d2015-06-30 14:04:14 +000025__shared_mutex_base::lock()
Howard Hinnant6185ace2013-09-21 01:49:28 +000026{
27 unique_lock<mutex> lk(__mut_);
28 while (__state_ & __write_entered_)
29 __gate1_.wait(lk);
30 __state_ |= __write_entered_;
31 while (__state_ & __n_readers_)
32 __gate2_.wait(lk);
33}
34
35bool
Marshall Clowac28c3d2015-06-30 14:04:14 +000036__shared_mutex_base::try_lock()
Howard Hinnant6185ace2013-09-21 01:49:28 +000037{
38 unique_lock<mutex> lk(__mut_);
39 if (__state_ == 0)
40 {
41 __state_ = __write_entered_;
42 return true;
43 }
44 return false;
45}
46
47void
Marshall Clowac28c3d2015-06-30 14:04:14 +000048__shared_mutex_base::unlock()
Howard Hinnant6185ace2013-09-21 01:49:28 +000049{
50 lock_guard<mutex> _(__mut_);
51 __state_ = 0;
52 __gate1_.notify_all();
53}
54
55// Shared ownership
56
57void
Marshall Clowac28c3d2015-06-30 14:04:14 +000058__shared_mutex_base::lock_shared()
Howard Hinnant6185ace2013-09-21 01:49:28 +000059{
60 unique_lock<mutex> lk(__mut_);
61 while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
62 __gate1_.wait(lk);
63 unsigned num_readers = (__state_ & __n_readers_) + 1;
64 __state_ &= ~__n_readers_;
65 __state_ |= num_readers;
66}
67
68bool
Marshall Clowac28c3d2015-06-30 14:04:14 +000069__shared_mutex_base::try_lock_shared()
Howard Hinnant6185ace2013-09-21 01:49:28 +000070{
71 unique_lock<mutex> lk(__mut_);
72 unsigned num_readers = __state_ & __n_readers_;
73 if (!(__state_ & __write_entered_) && num_readers != __n_readers_)
74 {
75 ++num_readers;
76 __state_ &= ~__n_readers_;
77 __state_ |= num_readers;
78 return true;
79 }
80 return false;
81}
82
83void
Marshall Clowac28c3d2015-06-30 14:04:14 +000084__shared_mutex_base::unlock_shared()
Howard Hinnant6185ace2013-09-21 01:49:28 +000085{
86 lock_guard<mutex> _(__mut_);
87 unsigned num_readers = (__state_ & __n_readers_) - 1;
88 __state_ &= ~__n_readers_;
89 __state_ |= num_readers;
90 if (__state_ & __write_entered_)
91 {
92 if (num_readers == 0)
93 __gate2_.notify_one();
94 }
95 else
96 {
97 if (num_readers == __n_readers_ - 1)
98 __gate1_.notify_one();
99 }
100}
101
102
Marshall Clowac28c3d2015-06-30 14:04:14 +0000103// Shared Timed Mutex
104// These routines are here for ABI stability
105shared_timed_mutex::shared_timed_mutex() : __base() {}
106void shared_timed_mutex::lock() { return __base.lock(); }
107bool shared_timed_mutex::try_lock() { return __base.try_lock(); }
108void shared_timed_mutex::unlock() { return __base.unlock(); }
109void shared_timed_mutex::lock_shared() { return __base.lock_shared(); }
110bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); }
111void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); }
112
Howard Hinnant6185ace2013-09-21 01:49:28 +0000113_LIBCPP_END_NAMESPACE_STD
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000114
115#endif // !_LIBCPP_HAS_NO_THREADS