Imported Upstream version 1.36.0
[platform/upstream/grpc.git] / src / core / lib / gprpp / sync.h
index 0a911b1..f385883 100644 (file)
@@ -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
 
 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