root / lab4 / .minix-src / include / c++ / __mutex_base
History | View | Annotate | Download (11.3 KB)
1 |
// -*- C++ -*- |
---|---|
2 |
//===----------------------------------------------------------------------===// |
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___MUTEX_BASE |
12 |
#define _LIBCPP___MUTEX_BASE |
13 |
|
14 |
#include <__config> |
15 |
#include <chrono> |
16 |
#include <system_error> |
17 |
#include <pthread.h> |
18 |
|
19 |
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
20 |
#pragma GCC system_header |
21 |
#endif |
22 |
|
23 |
_LIBCPP_BEGIN_NAMESPACE_STD |
24 |
|
25 |
#ifndef _LIBCPP_HAS_NO_THREADS |
26 |
|
27 |
class _LIBCPP_TYPE_VIS mutex |
28 |
{ |
29 |
pthread_mutex_t __m_; |
30 |
|
31 |
public: |
32 |
_LIBCPP_INLINE_VISIBILITY |
33 |
#ifndef _LIBCPP_HAS_NO_CONSTEXPR |
34 |
constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {} |
35 |
#else |
36 |
mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;} |
37 |
#endif |
38 |
~mutex(); |
39 |
|
40 |
private: |
41 |
mutex(const mutex&);// = delete; |
42 |
mutex& operator=(const mutex&);// = delete; |
43 |
|
44 |
public: |
45 |
void lock(); |
46 |
bool try_lock() _NOEXCEPT; |
47 |
void unlock() _NOEXCEPT; |
48 |
|
49 |
typedef pthread_mutex_t* native_handle_type; |
50 |
_LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} |
51 |
}; |
52 |
|
53 |
struct _LIBCPP_TYPE_VIS defer_lock_t {}; |
54 |
struct _LIBCPP_TYPE_VIS try_to_lock_t {}; |
55 |
struct _LIBCPP_TYPE_VIS adopt_lock_t {}; |
56 |
|
57 |
#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX) |
58 |
|
59 |
extern const defer_lock_t defer_lock; |
60 |
extern const try_to_lock_t try_to_lock; |
61 |
extern const adopt_lock_t adopt_lock; |
62 |
|
63 |
#else |
64 |
|
65 |
constexpr defer_lock_t defer_lock = defer_lock_t(); |
66 |
constexpr try_to_lock_t try_to_lock = try_to_lock_t(); |
67 |
constexpr adopt_lock_t adopt_lock = adopt_lock_t(); |
68 |
|
69 |
#endif |
70 |
|
71 |
template <class _Mutex> |
72 |
class _LIBCPP_TYPE_VIS_ONLY lock_guard |
73 |
{ |
74 |
public: |
75 |
typedef _Mutex mutex_type; |
76 |
|
77 |
private: |
78 |
mutex_type& __m_; |
79 |
public: |
80 |
|
81 |
_LIBCPP_INLINE_VISIBILITY |
82 |
explicit lock_guard(mutex_type& __m) |
83 |
: __m_(__m) {__m_.lock();} |
84 |
_LIBCPP_INLINE_VISIBILITY |
85 |
lock_guard(mutex_type& __m, adopt_lock_t) |
86 |
: __m_(__m) {} |
87 |
_LIBCPP_INLINE_VISIBILITY |
88 |
~lock_guard() {__m_.unlock();} |
89 |
|
90 |
private: |
91 |
lock_guard(lock_guard const&);// = delete; |
92 |
lock_guard& operator=(lock_guard const&);// = delete; |
93 |
}; |
94 |
|
95 |
template <class _Mutex> |
96 |
class _LIBCPP_TYPE_VIS_ONLY unique_lock |
97 |
{ |
98 |
public: |
99 |
typedef _Mutex mutex_type; |
100 |
|
101 |
private: |
102 |
mutex_type* __m_; |
103 |
bool __owns_; |
104 |
|
105 |
public: |
106 |
_LIBCPP_INLINE_VISIBILITY |
107 |
unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} |
108 |
_LIBCPP_INLINE_VISIBILITY |
109 |
explicit unique_lock(mutex_type& __m) |
110 |
: __m_(&__m), __owns_(true) {__m_->lock();} |
111 |
_LIBCPP_INLINE_VISIBILITY |
112 |
unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT |
113 |
: __m_(&__m), __owns_(false) {} |
114 |
_LIBCPP_INLINE_VISIBILITY |
115 |
unique_lock(mutex_type& __m, try_to_lock_t) |
116 |
: __m_(&__m), __owns_(__m.try_lock()) {} |
117 |
_LIBCPP_INLINE_VISIBILITY |
118 |
unique_lock(mutex_type& __m, adopt_lock_t) |
119 |
: __m_(&__m), __owns_(true) {} |
120 |
template <class _Clock, class _Duration> |
121 |
_LIBCPP_INLINE_VISIBILITY |
122 |
unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) |
123 |
: __m_(&__m), __owns_(__m.try_lock_until(__t)) {} |
124 |
template <class _Rep, class _Period> |
125 |
_LIBCPP_INLINE_VISIBILITY |
126 |
unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) |
127 |
: __m_(&__m), __owns_(__m.try_lock_for(__d)) {} |
128 |
_LIBCPP_INLINE_VISIBILITY |
129 |
~unique_lock() |
130 |
{ |
131 |
if (__owns_) |
132 |
__m_->unlock(); |
133 |
} |
134 |
|
135 |
private: |
136 |
unique_lock(unique_lock const&); // = delete; |
137 |
unique_lock& operator=(unique_lock const&); // = delete; |
138 |
|
139 |
public: |
140 |
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
141 |
_LIBCPP_INLINE_VISIBILITY |
142 |
unique_lock(unique_lock&& __u) _NOEXCEPT |
143 |
: __m_(__u.__m_), __owns_(__u.__owns_) |
144 |
{__u.__m_ = nullptr; __u.__owns_ = false;} |
145 |
_LIBCPP_INLINE_VISIBILITY |
146 |
unique_lock& operator=(unique_lock&& __u) _NOEXCEPT |
147 |
{ |
148 |
if (__owns_) |
149 |
__m_->unlock(); |
150 |
__m_ = __u.__m_; |
151 |
__owns_ = __u.__owns_; |
152 |
__u.__m_ = nullptr; |
153 |
__u.__owns_ = false; |
154 |
return *this; |
155 |
} |
156 |
|
157 |
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
158 |
|
159 |
void lock(); |
160 |
bool try_lock(); |
161 |
|
162 |
template <class _Rep, class _Period> |
163 |
bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); |
164 |
template <class _Clock, class _Duration> |
165 |
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
166 |
|
167 |
void unlock(); |
168 |
|
169 |
_LIBCPP_INLINE_VISIBILITY |
170 |
void swap(unique_lock& __u) _NOEXCEPT |
171 |
{ |
172 |
_VSTD::swap(__m_, __u.__m_); |
173 |
_VSTD::swap(__owns_, __u.__owns_); |
174 |
} |
175 |
_LIBCPP_INLINE_VISIBILITY |
176 |
mutex_type* release() _NOEXCEPT |
177 |
{ |
178 |
mutex_type* __m = __m_; |
179 |
__m_ = nullptr; |
180 |
__owns_ = false; |
181 |
return __m; |
182 |
} |
183 |
|
184 |
_LIBCPP_INLINE_VISIBILITY |
185 |
bool owns_lock() const _NOEXCEPT {return __owns_;} |
186 |
_LIBCPP_INLINE_VISIBILITY |
187 |
_LIBCPP_EXPLICIT |
188 |
operator bool () const _NOEXCEPT {return __owns_;} |
189 |
_LIBCPP_INLINE_VISIBILITY |
190 |
mutex_type* mutex() const _NOEXCEPT {return __m_;} |
191 |
}; |
192 |
|
193 |
template <class _Mutex> |
194 |
void |
195 |
unique_lock<_Mutex>::lock() |
196 |
{ |
197 |
if (__m_ == nullptr) |
198 |
__throw_system_error(EPERM, "unique_lock::lock: references null mutex"); |
199 |
if (__owns_) |
200 |
__throw_system_error(EDEADLK, "unique_lock::lock: already locked"); |
201 |
__m_->lock(); |
202 |
__owns_ = true; |
203 |
} |
204 |
|
205 |
template <class _Mutex> |
206 |
bool |
207 |
unique_lock<_Mutex>::try_lock() |
208 |
{ |
209 |
if (__m_ == nullptr) |
210 |
__throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); |
211 |
if (__owns_) |
212 |
__throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); |
213 |
__owns_ = __m_->try_lock(); |
214 |
return __owns_; |
215 |
} |
216 |
|
217 |
template <class _Mutex> |
218 |
template <class _Rep, class _Period> |
219 |
bool |
220 |
unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
221 |
{ |
222 |
if (__m_ == nullptr) |
223 |
__throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); |
224 |
if (__owns_) |
225 |
__throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); |
226 |
__owns_ = __m_->try_lock_for(__d); |
227 |
return __owns_; |
228 |
} |
229 |
|
230 |
template <class _Mutex> |
231 |
template <class _Clock, class _Duration> |
232 |
bool |
233 |
unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) |
234 |
{ |
235 |
if (__m_ == nullptr) |
236 |
__throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); |
237 |
if (__owns_) |
238 |
__throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); |
239 |
__owns_ = __m_->try_lock_until(__t); |
240 |
return __owns_; |
241 |
} |
242 |
|
243 |
template <class _Mutex> |
244 |
void |
245 |
unique_lock<_Mutex>::unlock() |
246 |
{ |
247 |
if (!__owns_) |
248 |
__throw_system_error(EPERM, "unique_lock::unlock: not locked"); |
249 |
__m_->unlock(); |
250 |
__owns_ = false; |
251 |
} |
252 |
|
253 |
template <class _Mutex> |
254 |
inline _LIBCPP_INLINE_VISIBILITY |
255 |
void |
256 |
swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT |
257 |
{__x.swap(__y);} |
258 |
|
259 |
//enum class cv_status |
260 |
_LIBCPP_DECLARE_STRONG_ENUM(cv_status) |
261 |
{ |
262 |
no_timeout, |
263 |
timeout |
264 |
}; |
265 |
_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) |
266 |
|
267 |
class _LIBCPP_TYPE_VIS condition_variable |
268 |
{ |
269 |
pthread_cond_t __cv_; |
270 |
public: |
271 |
_LIBCPP_INLINE_VISIBILITY |
272 |
#ifndef _LIBCPP_HAS_NO_CONSTEXPR |
273 |
constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {} |
274 |
#else |
275 |
condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;} |
276 |
#endif |
277 |
~condition_variable(); |
278 |
|
279 |
private: |
280 |
condition_variable(const condition_variable&); // = delete; |
281 |
condition_variable& operator=(const condition_variable&); // = delete; |
282 |
|
283 |
public: |
284 |
void notify_one() _NOEXCEPT; |
285 |
void notify_all() _NOEXCEPT; |
286 |
|
287 |
void wait(unique_lock<mutex>& __lk) _NOEXCEPT; |
288 |
template <class _Predicate> |
289 |
void wait(unique_lock<mutex>& __lk, _Predicate __pred); |
290 |
|
291 |
template <class _Clock, class _Duration> |
292 |
cv_status |
293 |
wait_until(unique_lock<mutex>& __lk, |
294 |
const chrono::time_point<_Clock, _Duration>& __t); |
295 |
|
296 |
template <class _Clock, class _Duration, class _Predicate> |
297 |
bool |
298 |
wait_until(unique_lock<mutex>& __lk, |
299 |
const chrono::time_point<_Clock, _Duration>& __t, |
300 |
_Predicate __pred); |
301 |
|
302 |
template <class _Rep, class _Period> |
303 |
cv_status |
304 |
wait_for(unique_lock<mutex>& __lk, |
305 |
const chrono::duration<_Rep, _Period>& __d); |
306 |
|
307 |
template <class _Rep, class _Period, class _Predicate> |
308 |
bool |
309 |
wait_for(unique_lock<mutex>& __lk, |
310 |
const chrono::duration<_Rep, _Period>& __d, |
311 |
_Predicate __pred); |
312 |
|
313 |
typedef pthread_cond_t* native_handle_type; |
314 |
_LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} |
315 |
|
316 |
private: |
317 |
void __do_timed_wait(unique_lock<mutex>& __lk, |
318 |
chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; |
319 |
}; |
320 |
#endif // !_LIBCPP_HAS_NO_THREADS |
321 |
|
322 |
template <class _To, class _Rep, class _Period> |
323 |
inline _LIBCPP_INLINE_VISIBILITY |
324 |
typename enable_if |
325 |
< |
326 |
chrono::__is_duration<_To>::value, |
327 |
_To |
328 |
>::type |
329 |
__ceil(chrono::duration<_Rep, _Period> __d) |
330 |
{ |
331 |
using namespace chrono; |
332 |
_To __r = duration_cast<_To>(__d); |
333 |
if (__r < __d) |
334 |
++__r; |
335 |
return __r; |
336 |
} |
337 |
|
338 |
#ifndef _LIBCPP_HAS_NO_THREADS |
339 |
template <class _Predicate> |
340 |
void |
341 |
condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) |
342 |
{ |
343 |
while (!__pred()) |
344 |
wait(__lk); |
345 |
} |
346 |
|
347 |
template <class _Clock, class _Duration> |
348 |
cv_status |
349 |
condition_variable::wait_until(unique_lock<mutex>& __lk, |
350 |
const chrono::time_point<_Clock, _Duration>& __t) |
351 |
{ |
352 |
using namespace chrono; |
353 |
wait_for(__lk, __t - _Clock::now()); |
354 |
return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; |
355 |
} |
356 |
|
357 |
template <class _Clock, class _Duration, class _Predicate> |
358 |
bool |
359 |
condition_variable::wait_until(unique_lock<mutex>& __lk, |
360 |
const chrono::time_point<_Clock, _Duration>& __t, |
361 |
_Predicate __pred) |
362 |
{ |
363 |
while (!__pred()) |
364 |
{ |
365 |
if (wait_until(__lk, __t) == cv_status::timeout) |
366 |
return __pred(); |
367 |
} |
368 |
return true; |
369 |
} |
370 |
|
371 |
template <class _Rep, class _Period> |
372 |
cv_status |
373 |
condition_variable::wait_for(unique_lock<mutex>& __lk, |
374 |
const chrono::duration<_Rep, _Period>& __d) |
375 |
{ |
376 |
using namespace chrono; |
377 |
if (__d <= __d.zero()) |
378 |
return cv_status::timeout; |
379 |
typedef time_point<system_clock, duration<long double, nano> > __sys_tpf; |
380 |
typedef time_point<system_clock, nanoseconds> __sys_tpi; |
381 |
__sys_tpf _Max = __sys_tpi::max(); |
382 |
system_clock::time_point __s_now = system_clock::now(); |
383 |
steady_clock::time_point __c_now = steady_clock::now(); |
384 |
if (_Max - __d > __s_now) |
385 |
__do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d)); |
386 |
else |
387 |
__do_timed_wait(__lk, __sys_tpi::max()); |
388 |
return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : |
389 |
cv_status::timeout; |
390 |
} |
391 |
|
392 |
template <class _Rep, class _Period, class _Predicate> |
393 |
inline _LIBCPP_INLINE_VISIBILITY |
394 |
bool |
395 |
condition_variable::wait_for(unique_lock<mutex>& __lk, |
396 |
const chrono::duration<_Rep, _Period>& __d, |
397 |
_Predicate __pred) |
398 |
{ |
399 |
return wait_until(__lk, chrono::steady_clock::now() + __d, |
400 |
_VSTD::move(__pred)); |
401 |
} |
402 |
|
403 |
#endif // !_LIBCPP_HAS_NO_THREADS |
404 |
|
405 |
_LIBCPP_END_NAMESPACE_STD |
406 |
|
407 |
#endif // _LIBCPP___MUTEX_BASE |