diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2020-02-13 16:31:05 +0100 |
---|---|---|
committer | Shelley Vohr <shelley.vohr@gmail.com> | 2020-02-17 12:40:51 -0800 |
commit | e23023d6856168074efe64dc769303f169244c4f (patch) | |
tree | bfbebfd0a21c10f1f6f184df37c9f39e50c5d461 | |
parent | cd99dc73681aab48ebea5f0cd5f59113764318ce (diff) | |
download | node-new-e23023d6856168074efe64dc769303f169244c4f.tar.gz |
src: add ExclusiveAccess class
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 <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: David Carlier <devnexen@gmail.com>
-rw-r--r-- | src/node_mutex.h | 48 |
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: |