@@ -30,8 +30,10 @@ namespace repository {
3030
3131class NamedMutexStorage ::Impl {
3232 public:
33- std::mutex& AquireLock (const std::string& resource);
33+ std::mutex& AcquireLock (const std::string& resource);
3434 void ReleaseLock (const std::string& resource);
35+ std::condition_variable& GetLockCondition (const std::string& resource);
36+ std::mutex& GetLockMutex (const std::string& resource);
3537 void SetError (const std::string& resource, const client::ApiError& error);
3638 boost::optional<client::ApiError> GetError (const std::string& resource);
3739
@@ -40,13 +42,15 @@ class NamedMutexStorage::Impl {
4042 std::mutex mutex;
4143 uint32_t use_count{0u };
4244 boost::optional<client::ApiError> optional_error;
45+ std::condition_variable lock_condition;
46+ std::mutex lock_mutex;
4347 };
4448
4549 std::mutex mutex_;
4650 std::unordered_map<std::string, RefCounterMutex> mutexes_;
4751};
4852
49- std::mutex& NamedMutexStorage::Impl::AquireLock (const std::string& resource) {
53+ std::mutex& NamedMutexStorage::Impl::AcquireLock (const std::string& resource) {
5054 std::lock_guard<std::mutex> lock (mutex_);
5155 RefCounterMutex& ref_mutex = mutexes_[resource];
5256 ref_mutex.use_count ++;
@@ -66,6 +70,19 @@ void NamedMutexStorage::Impl::ReleaseLock(const std::string& resource) {
6670 }
6771}
6872
73+ std::condition_variable& NamedMutexStorage::Impl::GetLockCondition (
74+ const std::string& resource) {
75+ std::lock_guard<std::mutex> lock (mutex_);
76+ RefCounterMutex& ref_mutex = mutexes_[resource];
77+ return ref_mutex.lock_condition ;
78+ }
79+
80+ std::mutex& NamedMutexStorage::Impl::GetLockMutex (const std::string& resource) {
81+ std::lock_guard<std::mutex> lock (mutex_);
82+ RefCounterMutex& ref_mutex = mutexes_[resource];
83+ return ref_mutex.lock_mutex ;
84+ }
85+
6986void NamedMutexStorage::Impl::SetError (const std::string& resource,
7087 const client::ApiError& error) {
7188 std::lock_guard<std::mutex> lock (mutex_);
@@ -88,14 +105,23 @@ boost::optional<client::ApiError> NamedMutexStorage::Impl::GetError(
88105
89106NamedMutexStorage::NamedMutexStorage () : impl_(std::make_shared<Impl>()) {}
90107
91- std::mutex& NamedMutexStorage::AquireLock (const std::string& resource) {
92- return impl_->AquireLock (resource);
108+ std::mutex& NamedMutexStorage::AcquireLock (const std::string& resource) {
109+ return impl_->AcquireLock (resource);
93110}
94111
95112void NamedMutexStorage::ReleaseLock (const std::string& resource) {
96113 impl_->ReleaseLock (resource);
97114}
98115
116+ std::condition_variable& NamedMutexStorage::GetLockCondition (
117+ const std::string& resource) {
118+ return impl_->GetLockCondition (resource);
119+ }
120+
121+ std::mutex& NamedMutexStorage::GetLockMutex (const std::string& resource) {
122+ return impl_->GetLockMutex (resource);
123+ }
124+
99125void NamedMutexStorage::SetError (const std::string& resource,
100126 const client::ApiError& error) {
101127 impl_->SetError (resource, error);
@@ -112,14 +138,17 @@ NamedMutex::NamedMutex(NamedMutexStorage& storage, const std::string& name,
112138 context_{context},
113139 is_locked_{false },
114140 name_{name},
115- mutex_{storage_.AquireLock (name_)} {}
141+ mutex_{storage_.AcquireLock (name_)},
142+ lock_condition_{storage_.GetLockCondition (name_)},
143+ lock_mutex_{storage_.GetLockMutex (name_)} {}
116144
117145NamedMutex::~NamedMutex () { storage_.ReleaseLock (name_); }
118146
119147void NamedMutex::lock () {
120- while (!is_locked_ && !context_.IsCancelled ()) {
121- is_locked_ = mutex_.try_lock ();
122- std::this_thread::yield ();
148+ if (!context_.IsCancelled () && !try_lock ()) {
149+ std::unique_lock<std::mutex> unique_lock{lock_mutex_};
150+ lock_condition_.wait (unique_lock,
151+ [&] { return context_.IsCancelled () || try_lock (); });
123152 }
124153}
125154
@@ -129,6 +158,7 @@ void NamedMutex::unlock() {
129158 if (is_locked_) {
130159 mutex_.unlock ();
131160 is_locked_ = false ;
161+ lock_condition_.notify_all ();
132162 }
133163}
134164
0 commit comments