summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2020-02-13 16:31:05 +0100
committerShelley Vohr <shelley.vohr@gmail.com>2020-02-17 12:40:51 -0800
commite23023d6856168074efe64dc769303f169244c4f (patch)
treebfbebfd0a21c10f1f6f184df37c9f39e50c5d461
parentcd99dc73681aab48ebea5f0cd5f59113764318ce (diff)
downloadnode-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.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: