Changeset View
Changeset View
Standalone View
Standalone View
extern/opennurbs/opennurbs_sleeplock.h
- This file was added.
| #pragma once | |||||
| /* $NoKeywords: $ */ | |||||
| /* | |||||
| // | |||||
| // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. | |||||
| // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert | |||||
| // McNeel & Associates. | |||||
| // | |||||
| // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. | |||||
| // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF | |||||
| // MERCHANTABILITY ARE HEREBY DISCLAIMED. | |||||
| // | |||||
| // For complete openNURBS copyright information see <http://www.opennurbs.org>. | |||||
| // | |||||
| //////////////////////////////////////////////////////////////// | |||||
| */ | |||||
| #if !defined(OPENNURBS_SLEEPLOCK_INC_) | |||||
| #define OPENNURBS_SLEEPLOCK_INC_ | |||||
| #define OPENNURBS_SLEEPLOCK_AVAILABLE | |||||
| #if !defined(ON_COMPILER_MSC) || !defined(ON_RUNTIME_WIN) | |||||
| // Use std::atomic_lock and std::this_thread::sleep_for(std::chrono::milliseconds(...)) | |||||
| #define ON_SLEEPLOCK_USES_STD_ATOMIC_FLAG | |||||
| #else | |||||
| // Windows uses InterlockedExchange() and ::Sleep(...) because it | |||||
| // is 1.5 times faster than std::atomic_lock. | |||||
| #endif | |||||
| class ON_CLASS ON_SleepLock | |||||
| { | |||||
| public: | |||||
| ON_SleepLock() = default; | |||||
| ~ON_SleepLock() = default; | |||||
| private: | |||||
| ON_SleepLock(const ON_SleepLock&) = delete; | |||||
| ON_SleepLock& operator=(const ON_SleepLock&) = delete; | |||||
| public: | |||||
| enum : unsigned int | |||||
| { | |||||
| ///<summary> | |||||
| /// The default ON_SleepLock interval is 1/20 of a second to wait between attempts to obtain the lock. | |||||
| ///</summary> | |||||
| DefaultWaitInterval = 50, | |||||
| ///<summary> | |||||
| /// A ON_SleepLock interval of 1 millisecond (1/1000 second). | |||||
| ///</summary> | |||||
| OneMillisecond = 1, | |||||
| ///<summary> | |||||
| /// A ON_SleepLock interval of 1 second. | |||||
| ///</summary> | |||||
| OneSecond = 1000, | |||||
| ///<summary> | |||||
| /// A ON_SleepLock interval of 1 minute. | |||||
| ///</summary> | |||||
| OneMinute = 60000 | |||||
| }; | |||||
| /* | |||||
| Description: | |||||
| ON_SleepLock::IsLocked() is not reliable. Do not use it. It will be deleted in the next SDK. | |||||
| Returns: | |||||
| An unreliable value. | |||||
| */ | |||||
| ON_DEPRECATED_MSG("ON_SleepLock::IsLocked() is not reliable. Do not use it. It will be deleted in the next SDK.") | |||||
| bool IsLocked() const; | |||||
| /* | |||||
| Description: | |||||
| Gets the lock using a ON_SleepLock::DefaultWaitInterval millisecond wait interval with | |||||
| no maximum waiting time. | |||||
| Returns: | |||||
| This version of GetLock() always returns true. | |||||
| Remarks: | |||||
| You must call ReturnLock() when finished using the protected resource. | |||||
| */ | |||||
| bool GetLock(); | |||||
| /* | |||||
| Description: | |||||
| Attempts to get the lock a single time. | |||||
| Returns: | |||||
| True if the lock was aquired. False if the lock was not aquired because it was already locked. | |||||
| Remarks: | |||||
| If GetLockOrReturnFalse() returns true, then you must call ReturnLock() when finished using the protected resource. | |||||
| If GetLockOrReturnFalse() returns false, then you must not call ReturnLock(). | |||||
| */ | |||||
| bool GetLockOrReturnFalse(); | |||||
| /* | |||||
| Description: | |||||
| Gets the lock using a the specified waiting interval | |||||
| and maximum waiting time. | |||||
| Parameters: | |||||
| interval_wait_msecs - [in] | |||||
| number of milliseconds to wait between checking for the lock. | |||||
| If interval_wait_msecs is 0, then ON_SleepLock::DefaultWaitInterval is used. | |||||
| If interval_wait_msecs > max_wait_msecs > 0, | |||||
| then one attempt is made to get the lock. | |||||
| max_wait_msecs - [in] | |||||
| maximum number of milliseconds to wait for lock. | |||||
| If max_wait_msecs is 0, then no maximum wating time is used. | |||||
| Returns: | |||||
| True if the lock is obtained. | |||||
| False if the maximum waiting time expired without getting | |||||
| the lock. | |||||
| If GetLock() returns true, then you must call ReturnLock() when finished using the protected resource. | |||||
| If GetLock() returns false, then you must not call ReturnLock(). | |||||
| Remarks: | |||||
| It is easy and clear to people reading your code if you use values | |||||
| like | |||||
| ON_SleepLock::OneSecond, | |||||
| ON_SleepLock::OneSecond/10, | |||||
| 47*ON_SleepLock::OneSecond, | |||||
| ON_SleepLock::OneMinute, | |||||
| or | |||||
| ON_SleepLock::OneMinute/3 | |||||
| to specify the values for interval_wait_msecs and max_wait_msecs. | |||||
| */ | |||||
| bool GetLock( | |||||
| unsigned int interval_wait_msecs, | |||||
| unsigned int max_wait_msecs | |||||
| ); | |||||
| bool GetLock( | |||||
| unsigned int interval_wait_msecs, | |||||
| unsigned int max_wait_msecs, | |||||
| bool bStealLockAfterWaiting | |||||
| ); | |||||
| /* | |||||
| Description: | |||||
| Unconditionally returns the lock. | |||||
| Returns: | |||||
| True if the lock was changed from locked to unlocked. | |||||
| False if the lock was already unlocked. | |||||
| */ | |||||
| bool ReturnLock(); | |||||
| private: | |||||
| // When locked m_locked = 1, otherwise m_locked = 0 ; | |||||
| #if defined(ON_SLEEPLOCK_USES_STD_ATOMIC_FLAG) | |||||
| mutable std::atomic_flag m_lockedX = ATOMIC_FLAG_INIT; // = 0 | |||||
| #else | |||||
| // 1.5 times faster on Windows 10 | |||||
| int m_locked = 0; | |||||
| #endif | |||||
| }; | |||||
| class ON_CLASS ON_SleepLockGuard | |||||
| { | |||||
| public: | |||||
| /* | |||||
| Description: | |||||
| Calls sleep_lock.GetLock(). | |||||
| Parameters: | |||||
| sleep_lock - [in] | |||||
| ON_SleepLock to manage. | |||||
| */ | |||||
| ON_SleepLockGuard(class ON_SleepLock& sleep_lock); | |||||
| // Used by The ThreadSafe...() functions and for expert users | |||||
| // to use when managing memory controlled by this pool. Best | |||||
| // to ingnore this unless you have a very clear idea of what | |||||
| // you are doing, why you are doing it, and when you are doing it. | |||||
| // Otherwise, you'll find yourself waiting forever on a nested | |||||
| // access request. | |||||
| ON_SleepLockGuard(class ON_FixedSizePool& fsp); | |||||
| /* | |||||
| Description: | |||||
| Calls sleep_lock.GetLock(interval_wait_msecs,max_wait_msecs). | |||||
| Parameters: | |||||
| sleep_lock - [in] | |||||
| ON_SleepLock to manage. | |||||
| */ | |||||
| ON_SleepLockGuard( | |||||
| class ON_SleepLock& sleep_lock, | |||||
| unsigned int interval_wait_msecs, | |||||
| unsigned int max_wait_msecs | |||||
| ); | |||||
| /* | |||||
| Description: | |||||
| Calls sleep_lock.GetLock(interval_wait_msecs,max_wait_msecs,bStealLockAfterWaiting). | |||||
| Parameters: | |||||
| sleep_lock - [in] | |||||
| ON_SleepLock to manage. | |||||
| */ | |||||
| ON_SleepLockGuard( | |||||
| class ON_SleepLock& sleep_lock, | |||||
| unsigned int interval_wait_msecs, | |||||
| unsigned int max_wait_msecs, | |||||
| bool bStealLockAfterWaiting | |||||
| ); | |||||
| /* | |||||
| Description: | |||||
| Calls sleep_lock.ReturnLock(). | |||||
| */ | |||||
| ~ON_SleepLockGuard(); | |||||
| /* | |||||
| Description: | |||||
| If this instance has the lock, it is returned and the destructor does nothing. | |||||
| */ | |||||
| void ReturnLock(); | |||||
| /* | |||||
| Returns: | |||||
| True if this instance currently has the lock. | |||||
| */ | |||||
| const bool IsManagingLock() const; | |||||
| private: | |||||
| // Keep m_sleep_lock private. Never add a function that provides access to m_sleep_lock. | |||||
| class ON_SleepLock& m_sleep_lock; | |||||
| bool m_bIsManagingLock = false; | |||||
| private: | |||||
| ON_SleepLockGuard() = delete; | |||||
| ON_SleepLockGuard(const ON_SleepLockGuard&) = delete; | |||||
| ON_SleepLockGuard& operator=(const ON_SleepLockGuard&) = delete; | |||||
| public: | |||||
| ON_SleepLockGuard(const class ON_Brep&); | |||||
| }; | |||||
| #endif | |||||