From e23023d6856168074efe64dc769303f169244c4f Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 13 Feb 2020 16:31:05 +0100 Subject: [PATCH] src: add ExclusiveAccess class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to Rust's `std::sync::Mutex` in that it requires one to unwrap the object before accessing it, acquiring the mutex in the process. PR-URL: https://github.com/nodejs/node/pull/31717 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Anna Henningsen Reviewed-By: Tobias Nießen Reviewed-By: David Carlier --- src/node_mutex.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/node_mutex.h b/src/node_mutex.h index 807e1444f1eb8b..b82505cc639b7a 100644 --- a/src/node_mutex.h +++ b/src/node_mutex.h @@ -6,6 +6,9 @@ #include "util.h" #include "uv.h" +#include // std::shared_ptr +#include // std::forward + namespace node { template class ConditionVariableBase; @@ -15,6 +18,51 @@ struct LibuvMutexTraits; using ConditionVariable = ConditionVariableBase; using Mutex = MutexBase; +template +class ExclusiveAccess { + public: + ExclusiveAccess() = default; + + template + explicit ExclusiveAccess(Args&&... args) + : item_(std::forward(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& 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 shared_; + typename MutexT::ScopedLock scoped_lock_; + T* const pointer_; + }; + + private: + friend class ScopedLock; + MutexT mutex_; + T item_; +}; + template class MutexBase { public: