// -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP___SGX_MUTEX_BASE #define _LIBCPP___SGX_MUTEX_BASE #include <__config> #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD class _LIBCPP_TYPE_VIS mutex { sgx_thread_mutex_t __m_; public: _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_HAS_NO_CONSTEXPR constexpr mutex() _NOEXCEPT : __m_ SGX_THREAD_NONRECURSIVE_MUTEX_INITIALIZER {} #else mutex() _NOEXCEPT {__m_ = (sgx_thread_mutex_t)SGX_THREAD_NONRECURSIVE_MUTEX_INITIALIZER;} #endif ~mutex(); mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; public: void lock(); bool try_lock() _NOEXCEPT; void unlock() _NOEXCEPT; typedef sgx_thread_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} }; struct _LIBCPP_TYPE_VIS defer_lock_t {}; struct _LIBCPP_TYPE_VIS try_to_lock_t {}; struct _LIBCPP_TYPE_VIS adopt_lock_t {}; #if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX) extern const defer_lock_t defer_lock; extern const try_to_lock_t try_to_lock; extern const adopt_lock_t adopt_lock; #else constexpr defer_lock_t defer_lock = defer_lock_t(); constexpr try_to_lock_t try_to_lock = try_to_lock_t(); constexpr adopt_lock_t adopt_lock = adopt_lock_t(); #endif template class _LIBCPP_TYPE_VIS_ONLY lock_guard { public: typedef _Mutex mutex_type; private: mutex_type& __m_; public: _LIBCPP_INLINE_VISIBILITY explicit lock_guard(mutex_type& __m) : __m_(__m) {__m_.lock();} _LIBCPP_INLINE_VISIBILITY lock_guard(mutex_type& __m, adopt_lock_t) : __m_(__m) {} _LIBCPP_INLINE_VISIBILITY ~lock_guard() {__m_.unlock();} lock_guard(lock_guard const&) = delete; lock_guard& operator=(lock_guard const&) = delete; }; template class _LIBCPP_TYPE_VIS_ONLY unique_lock { public: typedef _Mutex mutex_type; private: mutex_type* __m_; bool __owns_; public: _LIBCPP_INLINE_VISIBILITY unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} _LIBCPP_INLINE_VISIBILITY explicit unique_lock(mutex_type& __m) : __m_(&__m), __owns_(true) {__m_->lock();} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT : __m_(&__m), __owns_(false) {} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, try_to_lock_t) : __m_(&__m), __owns_(__m.try_lock()) {} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, adopt_lock_t) : __m_(&__m), __owns_(true) {} _LIBCPP_INLINE_VISIBILITY ~unique_lock() { if (__owns_) __m_->unlock(); } unique_lock(unique_lock const&) = delete; unique_lock& operator=(unique_lock const&) = delete; public: #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY unique_lock(unique_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) {__u.__m_ = nullptr; __u.__owns_ = false;} _LIBCPP_INLINE_VISIBILITY unique_lock& operator=(unique_lock&& __u) _NOEXCEPT { if (__owns_) __m_->unlock(); __m_ = __u.__m_; __owns_ = __u.__owns_; __u.__m_ = nullptr; __u.__owns_ = false; return *this; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void lock(); bool try_lock(); void unlock(); _LIBCPP_INLINE_VISIBILITY void swap(unique_lock& __u) _NOEXCEPT { _VSTD::swap(__m_, __u.__m_); _VSTD::swap(__owns_, __u.__owns_); } _LIBCPP_INLINE_VISIBILITY mutex_type* release() _NOEXCEPT { mutex_type* __m = __m_; __m_ = nullptr; __owns_ = false; return __m; } _LIBCPP_INLINE_VISIBILITY bool owns_lock() const _NOEXCEPT {return __owns_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool () const _NOEXCEPT {return __owns_;} _LIBCPP_INLINE_VISIBILITY mutex_type* mutex() const _NOEXCEPT {return __m_;} }; template void unique_lock<_Mutex>::lock() { if (__m_ == nullptr) __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); if (__owns_) __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); __m_->lock(); __owns_ = true; } template bool unique_lock<_Mutex>::try_lock() { if (__m_ == nullptr) __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); if (__owns_) __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); __owns_ = __m_->try_lock(); return __owns_; } template void unique_lock<_Mutex>::unlock() { if (!__owns_) __throw_system_error(EPERM, "unique_lock::unlock: not locked"); __m_->unlock(); __owns_ = false; } template inline _LIBCPP_INLINE_VISIBILITY void swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT {__x.swap(__y);} //enum class cv_status _LIBCPP_DECLARE_STRONG_ENUM(cv_status) { no_timeout, timeout }; _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) class _LIBCPP_TYPE_VIS condition_variable { sgx_thread_cond_t __cv_; public: _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_HAS_NO_CONSTEXPR constexpr condition_variable() : __cv_ SGX_THREAD_COND_INITIALIZER {} #else condition_variable() {__cv_ = (pthread_cond_t)SGX_THREAD_COND_INITIALIZER;} #endif ~condition_variable(); condition_variable(const condition_variable&) = delete; condition_variable& operator=(const condition_variable&) = delete; void notify_one() _NOEXCEPT; void notify_all() _NOEXCEPT; void wait(unique_lock& __lk) _NOEXCEPT; template void wait(unique_lock& __lk, _Predicate __pred); typedef sgx_thread_cond_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} }; template void condition_variable::wait(unique_lock& __lk, _Predicate __pred) { while (!__pred()) wait(__lk); } _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___SGX_MUTEX_BASE