summaryrefslogtreecommitdiffstats
path: root/src/rocksdb/third-party/folly/folly/synchronization/detail/ProxyLockable.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/rocksdb/third-party/folly/folly/synchronization/detail/ProxyLockable.h')
-rw-r--r--src/rocksdb/third-party/folly/folly/synchronization/detail/ProxyLockable.h164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/rocksdb/third-party/folly/folly/synchronization/detail/ProxyLockable.h b/src/rocksdb/third-party/folly/folly/synchronization/detail/ProxyLockable.h
new file mode 100644
index 000000000..af922daf4
--- /dev/null
+++ b/src/rocksdb/third-party/folly/folly/synchronization/detail/ProxyLockable.h
@@ -0,0 +1,164 @@
+// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
+// This source code is licensed under both the GPLv2 (found in the
+// COPYING file in the root directory) and Apache 2.0 License
+// (found in the LICENSE.Apache file in the root directory).
+
+#pragma once
+
+#include <folly/Optional.h>
+
+#include <mutex>
+
+namespace folly {
+namespace detail {
+
+/**
+ * ProxyLockable is a "concept" that is used usually for mutexes that don't
+ * return void, but rather a proxy object that contains data that should be
+ * passed to the unlock function.
+ *
+ * This is in contrast with the normal Lockable concept that imposes no
+ * requirement on the return type of lock(), and requires an unlock() with no
+ * parameters. Here we require that lock() returns non-void and that unlock()
+ * accepts the return type of lock() by value, rvalue-reference or
+ * const-reference
+ *
+ * Here we define two classes, that can be used by the top level to implement
+ * specializations for std::unique_lock and std::lock_guard. Both
+ * ProxyLockableUniqueLock and ProxyLockableLockGuard implement the entire
+ * interface of std::unique_lock and std::lock_guard respectively
+ */
+template <typename Mutex>
+class ProxyLockableUniqueLock {
+ public:
+ using mutex_type = Mutex;
+ using proxy_type =
+ _t<std::decay<decltype(std::declval<mutex_type>().lock())>>;
+
+ /**
+ * Default constructor initializes the unique_lock to an empty state
+ */
+ ProxyLockableUniqueLock() = default;
+
+ /**
+ * Destructor releases the mutex if it is locked
+ */
+ ~ProxyLockableUniqueLock();
+
+ /**
+ * Move constructor and move assignment operators take state from the other
+ * lock
+ */
+ ProxyLockableUniqueLock(ProxyLockableUniqueLock&& other) noexcept;
+ ProxyLockableUniqueLock& operator=(ProxyLockableUniqueLock&&) noexcept;
+
+ /**
+ * Locks the mutex, blocks until the mutex can be acquired.
+ *
+ * The mutex is guaranteed to be acquired after this function returns.
+ */
+ ProxyLockableUniqueLock(mutex_type&) noexcept;
+
+ /**
+ * Explicit locking constructors to control how the lock() method is called
+ *
+ * std::defer_lock_t causes the mutex to get tracked, but not locked
+ * std::try_to_lock_t causes try_lock() to be called. The current object is
+ * converts to true if the lock was successful
+ */
+ ProxyLockableUniqueLock(mutex_type& mtx, std::defer_lock_t) noexcept;
+ ProxyLockableUniqueLock(mutex_type& mtx, std::try_to_lock_t);
+
+ /**
+ * Timed locking constructors
+ */
+ template <typename Rep, typename Period>
+ ProxyLockableUniqueLock(
+ mutex_type& mtx,
+ const std::chrono::duration<Rep, Period>& duration);
+ template <typename Clock, typename Duration>
+ ProxyLockableUniqueLock(
+ mutex_type& mtx,
+ const std::chrono::time_point<Clock, Duration>& time);
+
+ /**
+ * Lock and unlock methods
+ *
+ * lock() and try_lock() throw if the mutex is already locked, or there is
+ * no mutex. unlock() throws if there is no mutex or if the mutex was not
+ * locked
+ */
+ void lock();
+ void unlock();
+ bool try_lock();
+
+ /**
+ * Timed locking methods
+ *
+ * These throw if there was no mutex, or if the mutex was already locked
+ */
+ template <typename Rep, typename Period>
+ bool try_lock_for(const std::chrono::duration<Rep, Period>& duration);
+ template <typename Clock, typename Duration>
+ bool try_lock_until(const std::chrono::time_point<Clock, Duration>& time);
+
+ /**
+ * Swap this unique lock with the other one
+ */
+ void swap(ProxyLockableUniqueLock& other) noexcept;
+
+ /**
+ * Returns true if the unique lock contains a lock and also has acquired an
+ * exclusive lock successfully
+ */
+ bool owns_lock() const noexcept;
+ explicit operator bool() const noexcept;
+
+ /**
+ * mutex() return a pointer to the mutex if there is a contained mutex and
+ * proxy() returns a pointer to the contained proxy if the mutex is locked
+ *
+ * If the unique lock was not constructed with a mutex, then mutex() returns
+ * nullptr. If the mutex is not locked, then proxy() returns nullptr
+ */
+ mutex_type* mutex() const noexcept;
+ proxy_type* proxy() const noexcept;
+
+ private:
+ friend class ProxyLockableTest;
+
+ /**
+ * If the optional has a value, the mutex is locked, if it is empty, it is
+ * not
+ */
+ mutable folly::Optional<proxy_type> proxy_{};
+ mutex_type* mutex_{nullptr};
+};
+
+template <typename Mutex>
+class ProxyLockableLockGuard : private ProxyLockableUniqueLock<Mutex> {
+ public:
+ using mutex_type = Mutex;
+
+ /**
+ * Constructor locks the mutex, and destructor unlocks
+ */
+ ProxyLockableLockGuard(mutex_type& mtx);
+ ~ProxyLockableLockGuard() = default;
+
+ /**
+ * This class is not movable or assignable
+ *
+ * For more complicated usecases, consider the UniqueLock variant, which
+ * provides more options
+ */
+ ProxyLockableLockGuard(const ProxyLockableLockGuard&) = delete;
+ ProxyLockableLockGuard(ProxyLockableLockGuard&&) = delete;
+ ProxyLockableLockGuard& operator=(ProxyLockableLockGuard&&) = delete;
+ ProxyLockableLockGuard& operator=(const ProxyLockableLockGuard&) = delete;
+};
+
+} // namespace detail
+} // namespace folly
+
+#include <folly/synchronization/detail/ProxyLockable-inl.h>