-
-/**
- * Free function adaptors for std:: and boost::
- */
-
-/**
- * Yields true iff T has .lock() and .unlock() member functions. This
- * is done by simply enumerating the mutexes with this interface in
- * std and boost.
- */
-template <class T>
-struct HasLockUnlock {
- enum { value = IsOneOf<T
- , std::mutex
- , std::recursive_mutex
- , boost::mutex
- , boost::recursive_mutex
- , boost::shared_mutex
-#if FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
- , std::timed_mutex
- , std::recursive_timed_mutex
- , boost::timed_mutex
- , boost::recursive_timed_mutex
-#endif
- >::value };
-};
-
-/**
- * Yields true iff T has .lock_shared() and .unlock_shared() member functions.
- * This is done by simply enumerating the mutexes with this interface.
- */
-template <class T>
-struct HasLockSharedUnlockShared {
- enum { value = IsOneOf<T
- , boost::shared_mutex
- >::value };
-};
-
-/**
- * Acquires a mutex for reading by calling .lock().
- *
- * This variant is not appropriate for shared mutexes.
- */
-template <class T>
-typename std::enable_if<
- HasLockUnlock<T>::value && !HasLockSharedUnlockShared<T>::value>::type
-acquireRead(T& mutex) {
- mutex.lock();
-}
-
-/**
- * Acquires a mutex for reading by calling .lock_shared().
- *
- * This variant is not appropriate for nonshared mutexes.
- */
-template <class T>
-typename std::enable_if<HasLockSharedUnlockShared<T>::value>::type
-acquireRead(T& mutex) {
- mutex.lock_shared();
-}
-
-/**
- * Acquires a mutex for reading and writing by calling .lock().
- */
-template <class T>
-typename std::enable_if<HasLockUnlock<T>::value>::type
-acquireReadWrite(T& mutex) {
- mutex.lock();
-}
-
-#if FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
-/**
- * Acquires a mutex for reading by calling .try_lock_shared_for(). This applies
- * to boost::shared_mutex.
- */
-template <class T>
-typename std::enable_if<
- IsOneOf<T
- , boost::shared_mutex
- >::value, bool>::type
-acquireRead(T& mutex,
- unsigned int milliseconds) {
- return mutex.try_lock_shared_for(boost::chrono::milliseconds(milliseconds));
-}
-
-/**
- * Acquires a mutex for reading and writing with timeout by calling
- * .try_lock_for(). This applies to two of the std mutex classes as
- * enumerated below.
- */
-template <class T>
-typename std::enable_if<
- IsOneOf<T
- , std::timed_mutex
- , std::recursive_timed_mutex
- >::value, bool>::type
-acquireReadWrite(T& mutex,
- unsigned int milliseconds) {
- // work around try_lock_for bug in some gcc versions, see
- // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54562
- // TODO: Fixed in gcc-4.9.0.
- return mutex.try_lock()
- || (milliseconds > 0 &&
- mutex.try_lock_until(std::chrono::system_clock::now() +
- std::chrono::milliseconds(milliseconds)));
-}
-
-/**
- * Acquires a mutex for reading and writing with timeout by calling
- * .try_lock_for(). This applies to three of the boost mutex classes as
- * enumerated below.
- */
-template <class T>
-typename std::enable_if<
- IsOneOf<T
- , boost::shared_mutex
- , boost::timed_mutex
- , boost::recursive_timed_mutex
- >::value, bool>::type
-acquireReadWrite(T& mutex,
- unsigned int milliseconds) {
- return mutex.try_lock_for(boost::chrono::milliseconds(milliseconds));
-}
-#endif // FOLLY_SYNCHRONIZED_HAVE_TIMED_MUTEXES
-
-/**
- * Releases a mutex previously acquired for reading by calling
- * .unlock(). The exception is boost::shared_mutex, which has a
- * special primitive called .unlock_shared().
- */
-template <class T>
-typename std::enable_if<
- HasLockUnlock<T>::value && !HasLockSharedUnlockShared<T>::value>::type
-releaseRead(T& mutex) {
- mutex.unlock();
-}
-
-/**
- * Special case for boost::shared_mutex.
- */
-template <class T>
-typename std::enable_if<HasLockSharedUnlockShared<T>::value>::type
-releaseRead(T& mutex) {
- mutex.unlock_shared();
-}
-
-/**
- * Releases a mutex previously acquired for reading-writing by calling
- * .unlock().
- */
-template <class T>
-typename std::enable_if<HasLockUnlock<T>::value>::type
-releaseReadWrite(T& mutex) {
- mutex.unlock();
-}
-