blob: 6185f15deabd6773724c3cb17d78465466e619b2 [file] [log] [blame]
Howard Hinnant6185ace2013-09-21 01:49:28 +00001//===---------------------- shared_mutex.cpp ------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000010#include "__config"
11#ifndef _LIBCPP_HAS_NO_THREADS
12
Howard Hinnant6185ace2013-09-21 01:49:28 +000013#include "shared_mutex"
14
15_LIBCPP_BEGIN_NAMESPACE_STD
16
Marshall Clowac28c3d2015-06-30 14:04:14 +000017// Shared Mutex Base
18__shared_mutex_base::__shared_mutex_base()
Howard Hinnant6185ace2013-09-21 01:49:28 +000019 : __state_(0)
20{
21}
22
23// Exclusive ownership
24
25void
Marshall Clowac28c3d2015-06-30 14:04:14 +000026__shared_mutex_base::lock()
Howard Hinnant6185ace2013-09-21 01:49:28 +000027{
28 unique_lock<mutex> lk(__mut_);
29 while (__state_ & __write_entered_)
30 __gate1_.wait(lk);
31 __state_ |= __write_entered_;
32 while (__state_ & __n_readers_)
33 __gate2_.wait(lk);
34}
35
36bool
Marshall Clowac28c3d2015-06-30 14:04:14 +000037__shared_mutex_base::try_lock()
Howard Hinnant6185ace2013-09-21 01:49:28 +000038{
39 unique_lock<mutex> lk(__mut_);
40 if (__state_ == 0)
41 {
42 __state_ = __write_entered_;
43 return true;
44 }
45 return false;
46}
47
48void
Marshall Clowac28c3d2015-06-30 14:04:14 +000049__shared_mutex_base::unlock()
Howard Hinnant6185ace2013-09-21 01:49:28 +000050{
51 lock_guard<mutex> _(__mut_);
52 __state_ = 0;
53 __gate1_.notify_all();
54}
55
56// Shared ownership
57
58void
Marshall Clowac28c3d2015-06-30 14:04:14 +000059__shared_mutex_base::lock_shared()
Howard Hinnant6185ace2013-09-21 01:49:28 +000060{
61 unique_lock<mutex> lk(__mut_);
62 while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
63 __gate1_.wait(lk);
64 unsigned num_readers = (__state_ & __n_readers_) + 1;
65 __state_ &= ~__n_readers_;
66 __state_ |= num_readers;
67}
68
69bool
Marshall Clowac28c3d2015-06-30 14:04:14 +000070__shared_mutex_base::try_lock_shared()
Howard Hinnant6185ace2013-09-21 01:49:28 +000071{
72 unique_lock<mutex> lk(__mut_);
73 unsigned num_readers = __state_ & __n_readers_;
74 if (!(__state_ & __write_entered_) && num_readers != __n_readers_)
75 {
76 ++num_readers;
77 __state_ &= ~__n_readers_;
78 __state_ |= num_readers;
79 return true;
80 }
81 return false;
82}
83
84void
Marshall Clowac28c3d2015-06-30 14:04:14 +000085__shared_mutex_base::unlock_shared()
Howard Hinnant6185ace2013-09-21 01:49:28 +000086{
87 lock_guard<mutex> _(__mut_);
88 unsigned num_readers = (__state_ & __n_readers_) - 1;
89 __state_ &= ~__n_readers_;
90 __state_ |= num_readers;
91 if (__state_ & __write_entered_)
92 {
93 if (num_readers == 0)
94 __gate2_.notify_one();
95 }
96 else
97 {
98 if (num_readers == __n_readers_ - 1)
99 __gate1_.notify_one();
100 }
101}
102
103
Marshall Clowac28c3d2015-06-30 14:04:14 +0000104// Shared Timed Mutex
105// These routines are here for ABI stability
106shared_timed_mutex::shared_timed_mutex() : __base() {}
107void shared_timed_mutex::lock() { return __base.lock(); }
108bool shared_timed_mutex::try_lock() { return __base.try_lock(); }
109void shared_timed_mutex::unlock() { return __base.unlock(); }
110void shared_timed_mutex::lock_shared() { return __base.lock_shared(); }
111bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); }
112void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); }
113
Howard Hinnant6185ace2013-09-21 01:49:28 +0000114_LIBCPP_END_NAMESPACE_STD
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000115
116#endif // !_LIBCPP_HAS_NO_THREADS