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