Skip to content

Commit

Permalink
src: add ExclusiveAccess class
Browse files Browse the repository at this point in the history
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: #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>
  • Loading branch information
bnoordhuis authored and codebytere committed Mar 30, 2020
1 parent 30dbc84 commit 01da656
Showing 1 changed file with 48 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/node_mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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:
Expand Down

0 comments on commit 01da656

Please sign in to comment.