16 #ifndef INCLUDE_NN_NLIB_THREADING_CRITICALSECTION_H_ 17 #define INCLUDE_NN_NLIB_THREADING_CRITICALSECTION_H_ 20 #include "nn/nlib/Swap.h" 29 #if defined(__cpp_constexpr) && defined(NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS) 43 void lock() NLIB_NOEXCEPT NLIB_ACQUIRE() {
48 void unlock() NLIB_NOEXCEPT NLIB_RELEASE() {
55 if (e == 0)
return true;
56 NLIB_ASSERT(e == EBUSY);
60 native_handle_type
native_handle() NLIB_NOEXCEPT NLIB_RETURN_CAPABILITY(mutex_) {
65 #if defined(__cpp_constexpr) && defined(NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS) 73 #ifndef NLIB_CRITICALSECTION_USE_FALLBACK 76 #if defined(__cpp_constexpr) && defined(NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS) 86 void lock() NLIB_NOEXCEPT NLIB_ACQUIRE() {
91 void unlock() NLIB_NOEXCEPT NLIB_RELEASE() {
98 if (e == 0)
return true;
99 NLIB_ASSERT(e == EBUSY);
103 native_handle_type
native_handle() NLIB_NOEXCEPT NLIB_RETURN_CAPABILITY(mutex_) {
108 #if defined(__cpp_constexpr) && defined(NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS) 117 #ifndef NLIB_TIMEDCRITICALSECTION_USE_FALLBACK 120 #if defined(__cpp_constexpr) && defined(NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS) 125 NLIB_ASSERT_NOERR(e);
132 NLIB_NOEXCEPT NLIB_TRY_ACQUIRE(
true);
133 void lock() NLIB_NOEXCEPT NLIB_ACQUIRE() {
135 NLIB_ASSERT_NOERR(e);
138 void unlock() NLIB_NOEXCEPT NLIB_RELEASE() {
140 NLIB_ASSERT_NOERR(e);
145 if (e == 0)
return true;
146 NLIB_ASSERT(e == EBUSY);
150 native_handle_type
native_handle() NLIB_NOEXCEPT NLIB_RETURN_CAPABILITY(mutex_) {
155 #if defined(__cpp_constexpr) && defined(NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS) 168 namespace threading {
170 class DummyCriticalSection NLIB_FINAL {
180 native_handle_type native_handle()
NLIB_NOEXCEPT {
return 0; }
186 class CriticalSectionFallback NLIB_FINAL {
198 native_handle_type native_handle() {
return lock_.native_handle(); }
206 #ifdef NLIB_CRITICALSECTION_USE_FALLBACK 210 class TimedCriticalSectionFallback NLIB_FINAL {
214 void lock()
NLIB_NOEXCEPT NLIB_NO_THREAD_SAFETY_ANALYSIS { lock_.lock(); }
215 void unlock()
NLIB_NOEXCEPT NLIB_NO_THREAD_SAFETY_ANALYSIS { lock_.unlock(); }
220 native_handle_type native_handle() {
return lock_.native_handle(); }
223 CriticalSection lock_;
226 #ifdef NLIB_TIMEDCRITICALSECTION_USE_FALLBACK 234 namespace threading {
249 explicit ScopedLock(mutex_type& m) NLIB_ACQUIRE(lock_) : lock_(m) {
256 return lock_.native_handle();
265 class NLIB_SCOPED_CAPABILITY ScopedLock<SimpleCriticalSection> NLIB_FINAL {
269 explicit ScopedLock(mutex_type& m) NLIB_ACQUIRE(lock_) : lock_(m) {
275 ~ScopedLock()
NLIB_NOEXCEPT NLIB_RELEASE(lock_) { lock_.unlock(); }
276 native_handle_type native_handle() NLIB_RETURN_CAPABILITY(lock_) {
277 return lock_.native_handle();
286 class NLIB_SCOPED_CAPABILITY ScopedLock<nlib_mutex> NLIB_FINAL {
290 explicit ScopedLock(mutex_type& m) NLIB_ACQUIRE(lock_) : lock_(m) {
293 NLIB_ASSERT_NOERR(e);
301 NLIB_ASSERT_NOERR(e);
303 native_handle_type native_handle() NLIB_RETURN_CAPABILITY(lock_) {
return &lock_; }
317 locker_(&rhs), is_locked_(true) {
321 NLIB_REQUIRES(locker_) : locker_(&rhs), is_locked_(true) {}
324 : locker_(&rhs), is_locked_(false) {}
327 is_locked_(rhs.try_lock()) {}
329 if (is_locked_) locker_->unlock();
331 #ifdef __cpp_rvalue_references 333 : locker_(rhs.locker_), is_locked_(rhs.is_locked_) {
334 rhs.locker_ =
nullptr;
335 rhs.is_locked_ =
false;
338 locker_ = rhs.locker_;
339 is_locked_ = rhs.is_locked_;
340 rhs.locker_ =
nullptr;
341 rhs.is_locked_ =
false;
346 : locker_(rhs.locker_), is_locked_(rhs.is_locked_) {
347 rhs.locker_ =
nullptr;
348 rhs.is_locked_ =
false;
351 locker_ = rhs.locker_;
352 is_locked_ = rhs.is_locked_;
353 rhs.locker_ =
nullptr;
354 rhs.is_locked_ =
false;
359 swap(locker_, rhs.locker_);
360 swap(is_locked_, rhs.is_locked_);
364 NLIB_ASSERT(locker_ && !is_locked_);
365 if (!locker_ || is_locked_) {
372 NLIB_ASSERT(locker_ && is_locked_);
373 if (!locker_ || !is_locked_) {
380 NLIB_ASSERT(locker_ && !is_locked_);
381 if (!locker_ || is_locked_) {
384 is_locked_ = locker_->try_lock();
389 NLIB_ASSERT(locker_ && !is_locked_);
390 if (!locker_ || is_locked_) {
393 is_locked_ = locker_->try_lock_for(timeout);
398 NLIB_ASSERT(locker_ && !is_locked_);
399 if (!locker_ || is_locked_) {
402 is_locked_ = locker_->try_lock_until(abstime);
406 mutex_type* p = locker_;
415 return locker_->native_handle();
430 return obj.native_handle();
434 NLIB_ALWAYS_INLINE nlib_mutex* GetRawMutex(nlib_mutex& obj) NLIB_RETURN_CAPABILITY(obj) {
443 NLIB_DEFINE_STD_SWAP_T_BEGIN3(
nn, nlib, threading)
444 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::UniqueLock)
445 NLIB_DEFINE_STD_SWAP_T_END3(
nn, nlib, threading)
447 #if defined(NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS) && !defined(NLIB_DOXYGEN) 449 bool nlib_is_error(NLIB_NS::threading::UniqueLock<T>&) =
delete;
455 #endif // INCLUDE_NN_NLIB_THREADING_CRITICALSECTION_H_ UniqueLock & assign(UniqueLock &rhs, move_tag) noexcept
ムーブ代入演算子に相当します。
UniqueLock(UniqueLock &rhs, move_tag) noexcept
ムーブコンストラクタに相当します。
native_handle_type native_handle() noexcept NLIB_RETURN_CAPABILITY(mutex_)
ネイティブ型のミューテックスのポインタを取得します。
bool try_lock() noexcept NLIB_TRY_ACQUIRE(true)
ロックを取得し、クリティカルセクションに入ることを試みます。
UniqueLock() noexcept
関連付けなしにオブジェクトを初期化します。
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
最も単純なクリティカルセクションです。リエントラントではありません。
mutex_type * mutex() const noexcept NLIB_RETURN_CAPABILITY(*locker_)
関連付けられているCriticalSection等のオブジェクトへのポインタを取得します。
mutex_type * release() noexcept NLIB_RETURN_CAPABILITY(*locker_)
関連付けを解除します。アンロックはされません。
bool try_lock_until(const DateTime &abstime) noexcept NLIB_TRY_ACQUIRE(true)
関連付けられたCriticalSection等のタイムアウト付きロックを試みます。
native_handle_type native_handle() NLIB_RETURN_CAPABILITY(lock_)
ロックを表す実装固有のハンドルを返します。
bool try_lock() noexcept NLIB_TRY_ACQUIRE(true)
ロックを取得し、クリティカルセクションに入ることを試みます。
mutex_type::native_handle_type native_handle_type
mutex_type::native_handle_type
bool owns_lock() const noexcept
UniqueLockに関連付けられたロックがロックされていればtrueを返します。
mutex_type::native_handle_type native_handle_type
mutex_type::native_handle_type
UniqueLock(mutex_type &rhs, AdoptLockType) NLIB_REQUIRES(locker_)
CriticalSection等が既にロックされていると仮定して、ロックせずにオブジェクトを初期化します。 デストラ...
void swap(UniqueLock &rhs) noexcept
関連付けられているCriticalSection等のオブジェクトをスワップします。
native_handle_type native_handle() NLIB_RETURN_CAPABILITY(*locker_)
ロックを表す実装固有のハンドルを返します。
空の構造体で、関数の引数をムーブすべきことを示すために利用されます。
タグ用の型でScopedLockとUniqueLockにおいて利用されます。
CriticalSection等をラップするためのクラスです。
nlib_mutex * native_handle_type
ネイティブのミューテックスへのポインタ型のtypedefです。
void lock() noexcept NLIB_ACQUIRE()
ロックを取得し、クリティカルセクションに入ります。取得できるまでブロックします。
UniqueLock & operator=(UniqueLock &&rhs) noexcept
ムーブ代入演算子です。C++11の利用時に有効です。
bool try_lock_for(const TimeSpan &timeout) noexcept NLIB_TRY_ACQUIRE(true)
関連付けられたCriticalSection等のタイムアウト付きロックを試みます。
ScopedLock(mutex_type &m) NLIB_ACQUIRE(lock_)
CriticalSection等をロックします(lock()を呼び出します)。
UniqueLock(mutex_type &rhs, DeferLockType) noexcept NLIB_EXCLUDES(locker_)
ロックせずにオブジェクトを初期化します。
void unlock() noexcept NLIB_RELEASE()
ロックを開放し、クリティカルセクションから出ます。
タグ用の型でScopedLockとUniqueLockにおいて利用されます。
nlib_mutex * native_handle_type
ネイティブのミューテックスへのポインタ型のtypedefです。
nlib_mutex * native_handle_type
ネイティブのミューテックスへのポインタ型のtypedefです。
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
constexpr const DeferLockType deferLock
DeferLockType 型の値です。
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
constexpr const AdoptLockType adoptLock
AdoptLockType 型の値です。
タグ用の型でScopedLockとUniqueLockにおいて利用されます。
UniqueLock(UniqueLock &&rhs) noexcept
ムーブコンストラクタです。C++11の利用時に有効です。
void unlock() noexcept NLIB_RELEASE()
関連付けられたCriticalSection等をアンロックします。
UniqueLock(mutex_type &rhs, TryToLockType)
初期化の際にtry_lock()でロックを試みます。
native_handle_type native_handle() noexcept NLIB_RETURN_CAPABILITY(mutex_)
ネイティブ型のミューテックスのポインタを取得します。
CriticalSection等をラップしてコンストラクタでロック、デストラクタでアンロックします。 ...
native_handle_type native_handle() noexcept NLIB_RETURN_CAPABILITY(mutex_)
ネイティブ型のミューテックスのポインタを取得します。
void lock() NLIB_ACQUIRE()
関連付けられたCriticalSection等をロックします。
void lock() noexcept NLIB_ACQUIRE()
ロックを取得し、クリティカルセクションに入ります。取得できるまでブロックします。
void lock() noexcept NLIB_ACQUIRE()
ロックを取得し、クリティカルセクションに入ります。取得できるまでブロックします。
bool try_lock() noexcept NLIB_TRY_ACQUIRE(true)
ロックを取得し、クリティカルセクションに入ることを試みます。
~ScopedLock() noexcept NLIB_RELEASE(lock_)
CriticalSection等をアンロックします(unlock()を呼び出します)。
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
void unlock() noexcept NLIB_RELEASE()
ロックを開放し、クリティカルセクションから出ます。
UniqueLock(mutex_type &rhs) NLIB_ACQUIRE(locker_)
CriticalSection等をロックして、このオブジェクトに関連付けます。
リエントラントでタイムアウトが可能なクリティカルセクションです。
constexpr const TryToLockType tryToLock
TryToLockType 型の値です。
void unlock() noexcept NLIB_RELEASE()
ロックを開放し、クリティカルセクションから出ます。
ScopedLock(mutex_type &m, AdoptLockType) noexcept NLIB_ACQUIRE(lock_)
CriticalSection等が既にロックされていると仮定して、ロックせずにオブジェクトを初期化します。 デストラ...
bool try_lock() noexcept NLIB_TRY_ACQUIRE(true)
関連付けられたCriticalSection等のロックを試みます。