diff options
Diffstat (limited to 'grpc/src/core/lib/gprpp/sync.h')
-rw-r--r-- | grpc/src/core/lib/gprpp/sync.h | 169 |
1 files changed, 129 insertions, 40 deletions
diff --git a/grpc/src/core/lib/gprpp/sync.h b/grpc/src/core/lib/gprpp/sync.h index 0a911b1c..f385883d 100644 --- a/grpc/src/core/lib/gprpp/sync.h +++ b/grpc/src/core/lib/gprpp/sync.h @@ -26,6 +26,9 @@ #include <grpc/support/sync.h> #include <grpc/support/time.h> +#include "absl/synchronization/mutex.h" +#include "src/core/lib/gprpp/time_util.h" + // The core library is not accessible in C++ codegen headers, and vice versa. // Thus, we need to have duplicate headers with similar functionality. // Make sure any change to this file is also reflected in @@ -37,7 +40,23 @@ namespace grpc_core { -class Mutex { +#ifdef GPR_ABSEIL_SYNC + +using Mutex = absl::Mutex; +using MutexLock = absl::MutexLock; +using ReleasableMutexLock = absl::ReleasableMutexLock; +using CondVar = absl::CondVar; + +// Returns the underlying gpr_mu from Mutex. This should be used only when +// it has to like passing the C++ mutex to C-core API. +// TODO(veblush): Remove this after C-core no longer uses gpr_mu. +inline gpr_mu* GetUnderlyingGprMu(Mutex* mutex) { + return reinterpret_cast<gpr_mu*>(mutex); +} + +#else + +class ABSL_LOCKABLE Mutex { public: Mutex() { gpr_mu_init(&mu_); } ~Mutex() { gpr_mu_destroy(&mu_); } @@ -45,52 +64,59 @@ class Mutex { Mutex(const Mutex&) = delete; Mutex& operator=(const Mutex&) = delete; - gpr_mu* get() { return &mu_; } - const gpr_mu* get() const { return &mu_; } + void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { gpr_mu_lock(&mu_); } + void Unlock() ABSL_UNLOCK_FUNCTION() { gpr_mu_unlock(&mu_); } + bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) { + return gpr_mu_trylock(&mu_) != 0; + } private: gpr_mu mu_; + + friend class CondVar; + friend gpr_mu* GetUnderlyingGprMu(Mutex* mutex); }; -// MutexLock is a std:: -class MutexLock { +// Returns the underlying gpr_mu from Mutex. This should be used only when +// it has to like passing the C++ mutex to C-core API. +// TODO(veblush): Remove this after C-core no longer uses gpr_mu. +inline gpr_mu* GetUnderlyingGprMu(Mutex* mutex) { return &mutex->mu_; } + +class ABSL_SCOPED_LOCKABLE MutexLock { public: - explicit MutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } - explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } - ~MutexLock() { gpr_mu_unlock(mu_); } + explicit MutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { + mu_->Lock(); + } + ~MutexLock() ABSL_UNLOCK_FUNCTION() { mu_->Unlock(); } MutexLock(const MutexLock&) = delete; MutexLock& operator=(const MutexLock&) = delete; private: - gpr_mu* const mu_; + Mutex* const mu_; }; -class ReleasableMutexLock { +class ABSL_SCOPED_LOCKABLE ReleasableMutexLock { public: - explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } - explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } - ~ReleasableMutexLock() { - if (!released_) gpr_mu_unlock(mu_); + explicit ReleasableMutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) + : mu_(mu) { + mu_->Lock(); + } + ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() { + if (!released_) mu_->Unlock(); } ReleasableMutexLock(const ReleasableMutexLock&) = delete; ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; - void Lock() { - GPR_DEBUG_ASSERT(released_); - gpr_mu_lock(mu_); - released_ = false; - } - - void Unlock() { + void Release() ABSL_UNLOCK_FUNCTION() { GPR_DEBUG_ASSERT(!released_); released_ = true; - gpr_mu_unlock(mu_); + mu_->Unlock(); } private: - gpr_mu* const mu_; + Mutex* const mu_; bool released_ = false; }; @@ -103,31 +129,94 @@ class CondVar { CondVar& operator=(const CondVar&) = delete; void Signal() { gpr_cv_signal(&cv_); } - void Broadcast() { gpr_cv_broadcast(&cv_); } + void SignalAll() { gpr_cv_broadcast(&cv_); } + + void Wait(Mutex* mu) { WaitWithDeadline(mu, absl::InfiniteFuture()); } + bool WaitWithTimeout(Mutex* mu, absl::Duration timeout) { + return gpr_cv_wait(&cv_, &mu->mu_, ToGprTimeSpec(timeout)) != 0; + } + bool WaitWithDeadline(Mutex* mu, absl::Time deadline) { + return gpr_cv_wait(&cv_, &mu->mu_, ToGprTimeSpec(deadline)) != 0; + } + + private: + gpr_cv cv_; +}; + +#endif // GPR_ABSEIL_SYNC + +template <typename Predicate> +static void WaitUntil(CondVar* cv, Mutex* mu, Predicate pred) { + while (!pred()) { + cv->Wait(mu); + } +} + +// Returns true iff we timed-out +template <typename Predicate> +static bool WaitUntilWithTimeout(CondVar* cv, Mutex* mu, Predicate pred, + absl::Duration timeout) { + while (!pred()) { + if (cv->WaitWithTimeout(mu, timeout)) return true; + } + return false; +} + +// Returns true iff we timed-out +template <typename Predicate> +static bool WaitUntilWithDeadline(CondVar* cv, Mutex* mu, Predicate pred, + absl::Time deadline) { + while (!pred()) { + if (cv->WaitWithDeadline(mu, deadline)) return true; + } + return false; +} + +// Deprecated. Prefer MutexLock +class MutexLockForGprMu { + public: + explicit MutexLockForGprMu(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } + ~MutexLockForGprMu() { gpr_mu_unlock(mu_); } + + MutexLockForGprMu(const MutexLock&) = delete; + MutexLockForGprMu& operator=(const MutexLock&) = delete; + + private: + gpr_mu* const mu_; +}; - int Wait(Mutex* mu) { return Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } - int Wait(Mutex* mu, const gpr_timespec& deadline) { - return gpr_cv_wait(&cv_, mu->get(), deadline); +// Deprecated. Prefer MutexLock or ReleasableMutexLock +class ABSL_SCOPED_LOCKABLE LockableAndReleasableMutexLock { + public: + explicit LockableAndReleasableMutexLock(Mutex* mu) + ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) + : mu_(mu) { + mu_->Lock(); } + ~LockableAndReleasableMutexLock() ABSL_UNLOCK_FUNCTION() { + if (!released_) mu_->Unlock(); + } + + LockableAndReleasableMutexLock(const LockableAndReleasableMutexLock&) = + delete; + LockableAndReleasableMutexLock& operator=( + const LockableAndReleasableMutexLock&) = delete; - template <typename Predicate> - void WaitUntil(Mutex* mu, Predicate pred) { - while (!pred()) { - Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } + void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { + GPR_DEBUG_ASSERT(released_); + mu_->Lock(); + released_ = false; } - // Returns true iff we timed-out - template <typename Predicate> - bool WaitUntil(Mutex* mu, Predicate pred, const gpr_timespec& deadline) { - while (!pred()) { - if (Wait(mu, deadline)) return true; - } - return false; + void Release() ABSL_UNLOCK_FUNCTION() { + GPR_DEBUG_ASSERT(!released_); + released_ = true; + mu_->Unlock(); } private: - gpr_cv cv_; + Mutex* const mu_; + bool released_ = false; }; } // namespace grpc_core |