00001 // Copyright 2017 The Abseil Authors. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // https://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 // 00015 // ----------------------------------------------------------------------------- 00016 // notification.h 00017 // ----------------------------------------------------------------------------- 00018 // 00019 // This header file defines a `Notification` abstraction, which allows threads 00020 // to receive notification of a single occurrence of a single event. 00021 // 00022 // The `Notification` object maintains a private boolean "notified" state that 00023 // transitions to `true` at most once. The `Notification` class provides the 00024 // following primary member functions: 00025 // * `HasBeenNotified() `to query its state 00026 // * `WaitForNotification*()` to have threads wait until the "notified" state 00027 // is `true`. 00028 // * `Notify()` to set the notification's "notified" state to `true` and 00029 // notify all waiting threads that the event has occurred. 00030 // This method may only be called once. 00031 // 00032 // Note that while `Notify()` may only be called once, it is perfectly valid to 00033 // call any of the `WaitForNotification*()` methods multiple times, from 00034 // multiple threads -- even after the notification's "notified" state has been 00035 // set -- in which case those methods will immediately return. 00036 // 00037 // Note that the lifetime of a `Notification` requires careful consideration; 00038 // it might not be safe to destroy a notification after calling `Notify()` since 00039 // it is still legal for other threads to call `WaitForNotification*()` methods 00040 // on the notification. However, observers responding to a "notified" state of 00041 // `true` can safely delete the notification without interfering with the call 00042 // to `Notify()` in the other thread. 00043 // 00044 // Memory ordering: For any threads X and Y, if X calls `Notify()`, then any 00045 // action taken by X before it calls `Notify()` is visible to thread Y after: 00046 // * Y returns from `WaitForNotification()`, or 00047 // * Y receives a `true` return value from either `HasBeenNotified()` or 00048 // `WaitForNotificationWithTimeout()`. 00049 00050 #ifndef ABSL_SYNCHRONIZATION_NOTIFICATION_H_ 00051 #define ABSL_SYNCHRONIZATION_NOTIFICATION_H_ 00052 00053 #include <atomic> 00054 00055 #include "absl/base/macros.h" 00056 #include "absl/synchronization/mutex.h" 00057 #include "absl/time/time.h" 00058 00059 namespace absl { 00060 00061 // ----------------------------------------------------------------------------- 00062 // Notification 00063 // ----------------------------------------------------------------------------- 00064 class Notification { 00065 public: 00066 // Initializes the "notified" state to unnotified. 00067 Notification() : notified_yet_(false) {} 00068 explicit Notification(bool prenotify) : notified_yet_(prenotify) {} 00069 Notification(const Notification&) = delete; 00070 Notification& operator=(const Notification&) = delete; 00071 ~Notification(); 00072 00073 // Notification::HasBeenNotified() 00074 // 00075 // Returns the value of the notification's internal "notified" state. 00076 bool HasBeenNotified() const; 00077 00078 // Notification::WaitForNotification() 00079 // 00080 // Blocks the calling thread until the notification's "notified" state is 00081 // `true`. Note that if `Notify()` has been previously called on this 00082 // notification, this function will immediately return. 00083 void WaitForNotification() const; 00084 00085 // Notification::WaitForNotificationWithTimeout() 00086 // 00087 // Blocks until either the notification's "notified" state is `true` (which 00088 // may occur immediately) or the timeout has elapsed, returning the value of 00089 // its "notified" state in either case. 00090 bool WaitForNotificationWithTimeout(absl::Duration timeout) const; 00091 00092 // Notification::WaitForNotificationWithDeadline() 00093 // 00094 // Blocks until either the notification's "notified" state is `true` (which 00095 // may occur immediately) or the deadline has expired, returning the value of 00096 // its "notified" state in either case. 00097 bool WaitForNotificationWithDeadline(absl::Time deadline) const; 00098 00099 // Notification::Notify() 00100 // 00101 // Sets the "notified" state of this notification to `true` and wakes waiting 00102 // threads. Note: do not call `Notify()` multiple times on the same 00103 // `Notification`; calling `Notify()` more than once on the same notification 00104 // results in undefined behavior. 00105 void Notify(); 00106 00107 private: 00108 mutable Mutex mutex_; 00109 std::atomic<bool> notified_yet_; // written under mutex_ 00110 }; 00111 00112 } // namespace absl 00113 00114 #endif // ABSL_SYNCHRONIZATION_NOTIFICATION_H_