about summary refs log tree commit diff
path: root/absl/synchronization/notification.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/synchronization/notification.h')
-rw-r--r--absl/synchronization/notification.h112
1 files changed, 112 insertions, 0 deletions
diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h
new file mode 100644
index 000000000000..107932f2909e
--- /dev/null
+++ b/absl/synchronization/notification.h
@@ -0,0 +1,112 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// notification.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines a `Notification` abstraction, which allows threads
+// to receive notification of a single occurrence of a single event.
+//
+// The `Notification` object maintains a private boolean "notified" state that
+// transitions to `true` at most once. The `Notification` class provides the
+// following primary member functions:
+//   * `HasBeenNotified() `to query its state
+//   * `WaitForNotification*()` to have threads wait until the "notified" state
+//      is `true`.
+//   * `Notify()` to set the notification's "notified" state to `true` and
+//     notify all waiting threads that the event has occurred.
+//     This method may only be called once.
+//
+// Note that while `Notify()` may only be called once, it is perfectly valid to
+// call any of the `WaitForNotification*()` methods multiple times, from
+// multiple threads -- even after the notification's "notified" state has been
+// set -- in which case those methods will immediately return.
+//
+// Note that the lifetime of a `Notification` requires careful consideration;
+// it might not be safe to destroy a notification after calling `Notify()` since
+// it is still legal for other threads to call `WaitForNotification*()` methods
+// on the notification. However, observers responding to a "notified" state of
+// `true` can safely delete the notification without interfering with the call
+// to `Notify()` in the other thread.
+//
+// Memory ordering: For any threads X and Y, if X calls `Notify()`, then any
+// action taken by X before it calls `Notify()` is visible to thread Y after:
+//  * Y returns from `WaitForNotification()`, or
+//  * Y receives a `true` return value from either `HasBeenNotified()` or
+//    `WaitForNotificationWithTimeout()`.
+
+#ifndef ABSL_SYNCHRONIZATION_NOTIFICATION_H_
+#define ABSL_SYNCHRONIZATION_NOTIFICATION_H_
+
+#include <atomic>
+
+#include "absl/synchronization/mutex.h"
+#include "absl/time/time.h"
+
+namespace absl {
+
+// -----------------------------------------------------------------------------
+// Notification
+// -----------------------------------------------------------------------------
+class Notification {
+ public:
+  // Initializes the "notified" state to unnotified.
+  Notification() : notified_yet_(false) {}
+  explicit Notification(bool prenotify) : notified_yet_(prenotify) {}
+  Notification(const Notification&) = delete;
+  Notification& operator=(const Notification&) = delete;
+  ~Notification();
+
+  // Notification::HasBeenNotified()
+  //
+  // Returns the value of the notification's internal "notified" state.
+  bool HasBeenNotified() const;
+
+  // Notification::WaitForNotification()
+  //
+  // Blocks the calling thread until the notification's "notified" state is
+  // `true`. Note that if `Notify()` has been previously called on this
+  // notification, this function will immediately return.
+  void WaitForNotification() const;
+
+  // Notification::WaitForNotificationWithTimeout()
+  //
+  // Blocks until either the notification's "notified" state is `true` (which
+  // may occur immediately) or the timeout has elapsed, returning the value of
+  // its "notified" state in either case.
+  bool WaitForNotificationWithTimeout(absl::Duration timeout) const;
+
+  // Notification::WaitForNotificationWithDeadline()
+  //
+  // Blocks until either the notification's "notified" state is `true` (which
+  // may occur immediately) or the deadline has expired, returning the value of
+  // its "notified" state in either case.
+  bool WaitForNotificationWithDeadline(absl::Time deadline) const;
+
+  // Notification::Notify()
+  //
+  // Sets the "notified" state of this notification to `true` and wakes waiting
+  // threads. Note: do not call `Notify()` multiple times on the same
+  // `Notification`; calling `Notify()` more than once on the same notification
+  // results in undefined behavior.
+  void Notify();
+
+ private:
+  mutable Mutex mutex_;
+  std::atomic<bool> notified_yet_;  // written under mutex_
+};
+
+}  // namespace absl
+#endif  // ABSL_SYNCHRONIZATION_NOTIFICATION_H_