source: mainline/uspace/lib/cpp/include/impl/shared_mutex.hpp@ 8a8a9273

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8a8a9273 was b3b8405, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: split <mutex> into <mutex> and <shared_mutex>

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_SHARED_MUTEX
30#define LIBCPP_SHARED_MUTEX
31
32#include <__bits/thread.hpp>
33#include <chrono>
34#include <mutex>
35
36namespace std
37{
38 /**
39 * 30.4.1.4.1, class shared_timed_mutex:
40 */
41
42 class shared_timed_mutex
43 {
44 public:
45 shared_timed_mutex() noexcept;
46 ~shared_timed_mutex();
47
48 shared_timed_mutex(const shared_timed_mutex&) = delete;
49 shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
50
51 void lock();
52 bool try_lock();
53 void unlock();
54
55 template<class Rep, class Period>
56 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
57 {
58 auto time = aux::threading::time::convert(rel_time);
59
60 return aux::threading::shared_mutex::try_lock_for(time);
61 }
62
63 template<class Clock, class Duration>
64 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
65 {
66 auto dur = (abs_time - Clock::now());
67 auto time = aux::threading::time::convert(dur);
68
69 return aux::threading::shared_mutex::try_lock_for(time);
70 }
71
72 void lock_shared();
73 bool try_lock_shared();
74 void unlock_shared();
75
76 template<class Rep, class Period>
77 bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
78 {
79 auto time = aux::threading::time::convert(rel_time);
80
81 return aux::threading::shared_mutex::try_lock_shared_for(time);
82 }
83
84 template<class Clock, class Duration>
85 bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
86 {
87 auto dur = (abs_time - Clock::now());
88 auto time = aux::threading::time::convert(dur);
89
90 return aux::threading::shared_mutex::try_lock_shared_for(time);
91 }
92
93 using native_handle_type = aux::shared_mutex_t*;
94 native_handle_type native_handle();
95
96 private:
97 aux::shared_mutex_t mtx_;
98 };
99
100 /**
101 * 30.4.2.3, class template shared_lock:
102 */
103
104 template<class Mutex>
105 class shared_lock
106 {
107 public:
108 using mutex_type = Mutex;
109
110 /**
111 * 30.4.2.2.1, construction/copy/destroy:
112 */
113
114 shared_lock() noexcept
115 : mtx_{nullptr}, owns_{false}
116 { /* DUMMY BODY */ }
117
118 explicit shared_lock(mutex_type& mtx)
119 : mtx_{&mtx}, owns_{true}
120 {
121 mtx_->lock_shared();
122 }
123
124 shared_lock(mutex_type& mtx, defer_lock_t) noexcept
125 : mtx_{&mtx}, owns_{false}
126 { /* DUMMY BODY */ }
127
128 shared_lock(mutex_type& mtx, try_to_lock_t)
129 : mtx_{&mtx}, owns_{}
130 {
131 owns_ = mtx_->try_lock_shared();
132 }
133
134 shared_lock(mutex_type& mtx, adopt_lock_t)
135 : mtx_{&mtx}, owns_{true}
136 { /* DUMMY BODY */ }
137
138 template<class Clock, class Duration>
139 shared_lock(mutex_type& mtx, const chrono::time_point<Clock, Duration>& abs_time)
140 : mtx_{&mtx}, owns_{}
141 {
142 owns_ = mtx_->try_lock_shared_until(abs_time);
143 }
144
145 template<class Rep, class Period>
146 shared_lock(mutex_type& mtx, const chrono::duration<Rep, Period>& rel_time)
147 : mtx_{&mtx}, owns_{}
148 {
149 owns_ = mtx_->try_lock_shared_for(rel_time);
150 }
151
152 ~shared_lock()
153 {
154 if (owns_)
155 mtx_->unlock_shared();
156 }
157
158 shared_lock(const shared_lock&) = delete;
159 shared_lock& operator=(const shared_lock&) = delete;
160
161 shared_lock(shared_lock&& other) noexcept
162 : mtx_{move(other.mtx_)}, owns_{move(other.owns_)}
163 {
164 other.mtx_ = nullptr;
165 other.owns_ = false;
166 }
167
168 shared_lock& operator=(shared_lock&& other)
169 {
170 if (owns_)
171 mtx_->unlock_shared();
172
173 mtx_ = move(other.mtx_);
174 owns_ = move(other.owns_);
175
176 other.mtx_ = nullptr;
177 other.owns_ = false;
178 }
179
180 /**
181 * 30.4.2.2.2, locking:
182 */
183
184 void lock()
185 {
186 /**
187 * TODO:
188 * throw system_error operation_not_permitted if mtx_ == nullptr
189 * throw system_error resource_deadlock_would_occur if owns_ == true
190 */
191
192 mtx_->lock_shared();
193 owns_ = true;
194 }
195
196 bool try_lock()
197 {
198 /**
199 * TODO:
200 * throw system_error operation_not_permitted if mtx_ == nullptr
201 * throw system_error resource_deadlock_would_occur if owns_ == true
202 */
203
204 owns_ = mtx_->try_lock_shared();
205
206 return owns_;
207 }
208
209 template<class Rep, class Period>
210 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
211 {
212 /**
213 * TODO:
214 * throw system_error operation_not_permitted if mtx_ == nullptr
215 * throw system_error resource_deadlock_would_occur if owns_ == true
216 */
217
218 owns_ = mtx_->try_lock_shared_for(rel_time);
219
220 return owns_;
221 }
222
223 template<class Clock, class Duration>
224 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
225 {
226 /**
227 * TODO:
228 * throw system_error operation_not_permitted if mtx_ == nullptr
229 * throw system_error resource_deadlock_would_occur if owns_ == true
230 */
231
232 owns_ = mtx_->try_lock_shared_until(abs_time);
233
234 return owns_;
235 }
236
237 void unlock()
238 {
239 /**
240 * TODO:
241 * throw system_error operation_not_permitted if owns_ == false
242 */
243
244 mtx_->unlock_shared();
245 }
246
247 /**
248 * 30.4.2.2.3, modifiers:
249 */
250
251 void swap(shared_lock& other) noexcept
252 {
253 std::swap(mtx_, other.mtx_);
254 std::swap(owns_, other.owns_);
255 }
256
257 mutex_type* release() noexcept
258 {
259 auto ret = mtx_;
260 mtx_ = nullptr;
261 owns_ = false;
262
263 return ret;
264 }
265
266 /**
267 * 30.4.2.2.4, observers:
268 */
269
270 bool owns_lock() const noexcept
271 {
272 return owns_;
273 }
274
275 explicit operator bool() const noexcept
276 {
277 return owns_;
278 }
279
280 mutex_type* mutex() const noexcept
281 {
282 return mtx_;
283 }
284
285 private:
286 mutex_type* mtx_;
287 bool owns_;
288 };
289
290 template<class Mutex>
291 void swap(shared_lock<Mutex>& lhs, shared_lock<Mutex>& rhs) noexcept
292 {
293 lhs.swap(rhs);
294 }
295}
296
297#endif
Note: See TracBrowser for help on using the repository browser.