summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/node_mutex.h48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/node_mutex.h b/src/node_mutex.h
index 807e1444f1..b82505cc63 100644
--- a/src/node_mutex.h
+++ b/src/node_mutex.h
@@ -6,6 +6,9 @@
#include "util.h"
#include "uv.h"
+#include <memory> // std::shared_ptr<T>
+#include <utility> // std::forward<T>
+
namespace node {
template <typename Traits> class ConditionVariableBase;
@@ -15,6 +18,51 @@ struct LibuvMutexTraits;
using ConditionVariable = ConditionVariableBase<LibuvMutexTraits>;
using Mutex = MutexBase<LibuvMutexTraits>;
+template <typename T, typename MutexT = Mutex>
+class ExclusiveAccess {
+ public:
+ ExclusiveAccess() = default;
+
+ template <typename... Args>
+ explicit ExclusiveAccess(Args&&... args)
+ : item_(std::forward<Args>(args)...) {}
+
+ ExclusiveAccess(const ExclusiveAccess&) = delete;
+ ExclusiveAccess& operator=(const ExclusiveAccess&) = delete;
+
+ class Scoped {
+ public:
+ // ExclusiveAccess will commonly be used in conjuction with std::shared_ptr
+ // and without this constructor it's too easy to forget to keep a reference
+ // around to the shared_ptr while operating on the ExclusiveAccess object.
+ explicit Scoped(const std::shared_ptr<ExclusiveAccess>& shared)
+ : shared_(shared)
+ , scoped_lock_(shared->mutex_)
+ , pointer_(&shared->item_) {}
+
+ explicit Scoped(ExclusiveAccess* exclusive_access)
+ : shared_()
+ , scoped_lock_(exclusive_access->mutex_)
+ , pointer_(&exclusive_access->item_) {}
+
+ T& operator*() const { return *pointer_; }
+ T* operator->() const { return pointer_; }
+
+ Scoped(const Scoped&) = delete;
+ Scoped& operator=(const Scoped&) = delete;
+
+ private:
+ std::shared_ptr<ExclusiveAccess> shared_;
+ typename MutexT::ScopedLock scoped_lock_;
+ T* const pointer_;
+ };
+
+ private:
+ friend class ScopedLock;
+ MutexT mutex_;
+ T item_;
+};
+
template <typename Traits>
class MutexBase {
public: