diff options
Diffstat (limited to 'src/mongo/platform')
-rw-r--r-- | src/mongo/platform/condition_variable.cpp | 2 | ||||
-rw-r--r-- | src/mongo/platform/condition_variable.h | 14 | ||||
-rw-r--r-- | src/mongo/platform/condition_variable_test.cpp | 6 | ||||
-rw-r--r-- | src/mongo/platform/mutex.cpp | 18 | ||||
-rw-r--r-- | src/mongo/platform/mutex.h | 66 |
5 files changed, 73 insertions, 33 deletions
diff --git a/src/mongo/platform/condition_variable.cpp b/src/mongo/platform/condition_variable.cpp index 19abb58b8f8..ef6e64aaff7 100644 --- a/src/mongo/platform/condition_variable.cpp +++ b/src/mongo/platform/condition_variable.cpp @@ -27,6 +27,8 @@ * it in the license file. */ +#include "mongo/platform/basic.h" + #include "mongo/platform/condition_variable.h" namespace mongo { diff --git a/src/mongo/platform/condition_variable.h b/src/mongo/platform/condition_variable.h index 885e4b82ccd..beca4f4dda9 100644 --- a/src/mongo/platform/condition_variable.h +++ b/src/mongo/platform/condition_variable.h @@ -28,10 +28,12 @@ */ #pragma once -#include "mongo/platform/basic.h" + +#include <chrono> #include "mongo/platform/mutex.h" #include "mongo/stdx/condition_variable.h" +#include "mongo/util/duration.h" #include "mongo/util/scopeguard.h" namespace mongo { @@ -46,8 +48,6 @@ public: }; class ConditionVariable { - friend class ::mongo::Waitable; - public: static constexpr Milliseconds kUnfulfilledConditionVariableTimeout = Milliseconds(100); @@ -79,8 +79,10 @@ public: protected: template <typename Callback> - void _runWithNotifyable(Notifyable& notifyable, Callback&& cb) noexcept { - _condvar._runWithNotifyable(notifyable, cb); + friend void runWithNotifyable(ConditionVariable& cv, + Notifyable& notifyable, + Callback&& cb) noexcept { + runWithNotifyable(cv._condvar, notifyable, std::forward<Callback>(cb)); } private: @@ -105,7 +107,7 @@ private: } if (_conditionVariableActions) { - if constexpr (std::is_same<decltype(lock), Mutex>::value) { + if constexpr (std::is_same<decltype(lock), mongo::Mutex>::value) { _conditionVariableActions->onUnfulfilledConditionVariable(lock.getName()); } else { _conditionVariableActions->onUnfulfilledConditionVariable("AnonymousLock"); diff --git a/src/mongo/platform/condition_variable_test.cpp b/src/mongo/platform/condition_variable_test.cpp index 88e7a40c617..69631e233f2 100644 --- a/src/mongo/platform/condition_variable_test.cpp +++ b/src/mongo/platform/condition_variable_test.cpp @@ -39,11 +39,11 @@ namespace mongo { TEST(ConditionVariable, BasicSingleThread) { unittest::Barrier barrier(2U); ConditionVariable cv; - Mutex m; + stdx::mutex m; // NOLINT bool done = false; stdx::thread worker([&]() { - stdx::unique_lock<Mutex> lk(m); + stdx::unique_lock<stdx::mutex> lk(m); barrier.countDownAndWait(); ASSERT(!done); cv.wait(lk, [&] { return done; }); @@ -52,7 +52,7 @@ TEST(ConditionVariable, BasicSingleThread) { barrier.countDownAndWait(); { - stdx::unique_lock<Mutex> lk(m); + stdx::unique_lock<stdx::mutex> lk(m); done = true; } cv.notify_one(); diff --git a/src/mongo/platform/mutex.cpp b/src/mongo/platform/mutex.cpp index 49ececfd25e..ba7230f8e94 100644 --- a/src/mongo/platform/mutex.cpp +++ b/src/mongo/platform/mutex.cpp @@ -31,23 +31,19 @@ namespace mongo { -namespace { -std::unique_ptr<LockActions> gLockActions; -} - void Mutex::lock() { - auto hasLock = _mutex.try_lock_for(kContendedLockTimeout.toSystemDuration()); + auto hasLock = _mutex.try_lock(); if (hasLock) { return; } - if (gLockActions) { - gLockActions->onContendedLock(_name); + if (auto actions = LockActions::getState().actions.load()) { + actions->onContendedLock(_name); } _mutex.lock(); } void Mutex::unlock() { - if (gLockActions) { - gLockActions->onUnlock(_name); + if (auto actions = LockActions::getState().actions.load()) { + actions->onUnlock(_name); } _mutex.unlock(); } @@ -55,8 +51,8 @@ bool Mutex::try_lock() { return _mutex.try_lock(); } -void Mutex::setLockActions(std::unique_ptr<LockActions> actions) { - gLockActions = std::move(actions); +void Mutex::LockActions::add(LockActions* actions) { + getState().actions.store(actions); } } // namespace mongo diff --git a/src/mongo/platform/mutex.h b/src/mongo/platform/mutex.h index ded61a90783..fe72b201d3a 100644 --- a/src/mongo/platform/mutex.h +++ b/src/mongo/platform/mutex.h @@ -33,40 +33,80 @@ #include "mongo/base/error_codes.h" #include "mongo/base/string_data.h" +#include "mongo/platform/atomic_word.h" #include "mongo/stdx/mutex.h" -#include "mongo/util/clock_source_mock.h" +#include "mongo/util/duration.h" namespace mongo { -class LockActions { +class Latch { public: - virtual ~LockActions() = default; - virtual void onContendedLock(const StringData& name) = 0; - virtual void onUnlock(const StringData& name) = 0; + virtual ~Latch() = default; + + virtual void lock() = 0; + virtual void unlock() = 0; + virtual bool try_lock() = 0; }; -class Mutex { +class Mutex : public Latch { public: + class LockActions; static constexpr auto kAnonymousMutexStr = "AnonymousMutex"_sd; - static constexpr Milliseconds kContendedLockTimeout = Milliseconds(100); Mutex() : Mutex(kAnonymousMutexStr) {} // Note that StringData is a view type, thus the underlying string for _name must outlive any // given Mutex explicit Mutex(const StringData& name) : _name(name) {} - void lock(); - void unlock(); - bool try_lock(); + void lock() override; + void unlock() override; + bool try_lock() override; const StringData& getName() const { return _name; } - static void setLockActions(std::unique_ptr<LockActions> actions); - private: const StringData _name; - stdx::timed_mutex _mutex; + stdx::mutex _mutex; // NOLINT +}; + +/** + * A set of actions to happen upon notable events on a Lockable-conceptualized type + */ +class Mutex::LockActions { + friend class Mutex; + +public: + virtual ~LockActions() = default; + /** + * Action to do when a lock cannot be immediately acquired + */ + virtual void onContendedLock(const StringData& name) = 0; + + /** + * Action to do when a lock is unlocked + */ + virtual void onUnlock(const StringData& name) = 0; + + /** + * This function adds a LockActions subclass to the triggers for certain actions. + * + * Note that currently there is only one LockActions in use at a time. As part of SERVER-42895, + * this will change so that there is a list of LockActions maintained. + * + * LockActions can only be added and not removed. If you wish to deactivate a LockActions + * subclass, please provide the switch on that subclass to noop its functions. + */ + static void add(LockActions* actions); + +private: + static auto& getState() { + struct State { + AtomicWord<LockActions*> actions{nullptr}; + }; + static State state; + return state; + } }; } // namespace mongo |