1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker // 15*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 16*9356374aSAndroid Build Coastguard Worker // notification.h 17*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 18*9356374aSAndroid Build Coastguard Worker // 19*9356374aSAndroid Build Coastguard Worker // This header file defines a `Notification` abstraction, which allows threads 20*9356374aSAndroid Build Coastguard Worker // to receive notification of a single occurrence of a single event. 21*9356374aSAndroid Build Coastguard Worker // 22*9356374aSAndroid Build Coastguard Worker // The `Notification` object maintains a private boolean "notified" state that 23*9356374aSAndroid Build Coastguard Worker // transitions to `true` at most once. The `Notification` class provides the 24*9356374aSAndroid Build Coastguard Worker // following primary member functions: 25*9356374aSAndroid Build Coastguard Worker // * `HasBeenNotified()` to query its state 26*9356374aSAndroid Build Coastguard Worker // * `WaitForNotification*()` to have threads wait until the "notified" state 27*9356374aSAndroid Build Coastguard Worker // is `true`. 28*9356374aSAndroid Build Coastguard Worker // * `Notify()` to set the notification's "notified" state to `true` and 29*9356374aSAndroid Build Coastguard Worker // notify all waiting threads that the event has occurred. 30*9356374aSAndroid Build Coastguard Worker // This method may only be called once. 31*9356374aSAndroid Build Coastguard Worker // 32*9356374aSAndroid Build Coastguard Worker // Note that while `Notify()` may only be called once, it is perfectly valid to 33*9356374aSAndroid Build Coastguard Worker // call any of the `WaitForNotification*()` methods multiple times, from 34*9356374aSAndroid Build Coastguard Worker // multiple threads -- even after the notification's "notified" state has been 35*9356374aSAndroid Build Coastguard Worker // set -- in which case those methods will immediately return. 36*9356374aSAndroid Build Coastguard Worker // 37*9356374aSAndroid Build Coastguard Worker // Note that the lifetime of a `Notification` requires careful consideration; 38*9356374aSAndroid Build Coastguard Worker // it might not be safe to destroy a notification after calling `Notify()` since 39*9356374aSAndroid Build Coastguard Worker // it is still legal for other threads to call `WaitForNotification*()` methods 40*9356374aSAndroid Build Coastguard Worker // on the notification. However, observers responding to a "notified" state of 41*9356374aSAndroid Build Coastguard Worker // `true` can safely delete the notification without interfering with the call 42*9356374aSAndroid Build Coastguard Worker // to `Notify()` in the other thread. 43*9356374aSAndroid Build Coastguard Worker // 44*9356374aSAndroid Build Coastguard Worker // Memory ordering: For any threads X and Y, if X calls `Notify()`, then any 45*9356374aSAndroid Build Coastguard Worker // action taken by X before it calls `Notify()` is visible to thread Y after: 46*9356374aSAndroid Build Coastguard Worker // * Y returns from `WaitForNotification()`, or 47*9356374aSAndroid Build Coastguard Worker // * Y receives a `true` return value from either `HasBeenNotified()` or 48*9356374aSAndroid Build Coastguard Worker // `WaitForNotificationWithTimeout()`. 49*9356374aSAndroid Build Coastguard Worker 50*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_SYNCHRONIZATION_NOTIFICATION_H_ 51*9356374aSAndroid Build Coastguard Worker #define ABSL_SYNCHRONIZATION_NOTIFICATION_H_ 52*9356374aSAndroid Build Coastguard Worker 53*9356374aSAndroid Build Coastguard Worker #include <atomic> 54*9356374aSAndroid Build Coastguard Worker 55*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h" 56*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h" 57*9356374aSAndroid Build Coastguard Worker #include "absl/time/time.h" 58*9356374aSAndroid Build Coastguard Worker 59*9356374aSAndroid Build Coastguard Worker namespace absl { 60*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 61*9356374aSAndroid Build Coastguard Worker 62*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 63*9356374aSAndroid Build Coastguard Worker // Notification 64*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 65*9356374aSAndroid Build Coastguard Worker class Notification { 66*9356374aSAndroid Build Coastguard Worker public: 67*9356374aSAndroid Build Coastguard Worker // Initializes the "notified" state to unnotified. Notification()68*9356374aSAndroid Build Coastguard Worker Notification() : notified_yet_(false) {} Notification(bool prenotify)69*9356374aSAndroid Build Coastguard Worker explicit Notification(bool prenotify) : notified_yet_(prenotify) {} 70*9356374aSAndroid Build Coastguard Worker Notification(const Notification&) = delete; 71*9356374aSAndroid Build Coastguard Worker Notification& operator=(const Notification&) = delete; 72*9356374aSAndroid Build Coastguard Worker ~Notification(); 73*9356374aSAndroid Build Coastguard Worker 74*9356374aSAndroid Build Coastguard Worker // Notification::HasBeenNotified() 75*9356374aSAndroid Build Coastguard Worker // 76*9356374aSAndroid Build Coastguard Worker // Returns the value of the notification's internal "notified" state. HasBeenNotified()77*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool HasBeenNotified() const { 78*9356374aSAndroid Build Coastguard Worker return HasBeenNotifiedInternal(&this->notified_yet_); 79*9356374aSAndroid Build Coastguard Worker } 80*9356374aSAndroid Build Coastguard Worker 81*9356374aSAndroid Build Coastguard Worker // Notification::WaitForNotification() 82*9356374aSAndroid Build Coastguard Worker // 83*9356374aSAndroid Build Coastguard Worker // Blocks the calling thread until the notification's "notified" state is 84*9356374aSAndroid Build Coastguard Worker // `true`. Note that if `Notify()` has been previously called on this 85*9356374aSAndroid Build Coastguard Worker // notification, this function will immediately return. 86*9356374aSAndroid Build Coastguard Worker void WaitForNotification() const; 87*9356374aSAndroid Build Coastguard Worker 88*9356374aSAndroid Build Coastguard Worker // Notification::WaitForNotificationWithTimeout() 89*9356374aSAndroid Build Coastguard Worker // 90*9356374aSAndroid Build Coastguard Worker // Blocks until either the notification's "notified" state is `true` (which 91*9356374aSAndroid Build Coastguard Worker // may occur immediately) or the timeout has elapsed, returning the value of 92*9356374aSAndroid Build Coastguard Worker // its "notified" state in either case. 93*9356374aSAndroid Build Coastguard Worker bool WaitForNotificationWithTimeout(absl::Duration timeout) const; 94*9356374aSAndroid Build Coastguard Worker 95*9356374aSAndroid Build Coastguard Worker // Notification::WaitForNotificationWithDeadline() 96*9356374aSAndroid Build Coastguard Worker // 97*9356374aSAndroid Build Coastguard Worker // Blocks until either the notification's "notified" state is `true` (which 98*9356374aSAndroid Build Coastguard Worker // may occur immediately) or the deadline has expired, returning the value of 99*9356374aSAndroid Build Coastguard Worker // its "notified" state in either case. 100*9356374aSAndroid Build Coastguard Worker bool WaitForNotificationWithDeadline(absl::Time deadline) const; 101*9356374aSAndroid Build Coastguard Worker 102*9356374aSAndroid Build Coastguard Worker // Notification::Notify() 103*9356374aSAndroid Build Coastguard Worker // 104*9356374aSAndroid Build Coastguard Worker // Sets the "notified" state of this notification to `true` and wakes waiting 105*9356374aSAndroid Build Coastguard Worker // threads. Note: do not call `Notify()` multiple times on the same 106*9356374aSAndroid Build Coastguard Worker // `Notification`; calling `Notify()` more than once on the same notification 107*9356374aSAndroid Build Coastguard Worker // results in undefined behavior. 108*9356374aSAndroid Build Coastguard Worker void Notify(); 109*9356374aSAndroid Build Coastguard Worker 110*9356374aSAndroid Build Coastguard Worker private: HasBeenNotifiedInternal(const std::atomic<bool> * notified_yet)111*9356374aSAndroid Build Coastguard Worker static inline bool HasBeenNotifiedInternal( 112*9356374aSAndroid Build Coastguard Worker const std::atomic<bool>* notified_yet) { 113*9356374aSAndroid Build Coastguard Worker return notified_yet->load(std::memory_order_acquire); 114*9356374aSAndroid Build Coastguard Worker } 115*9356374aSAndroid Build Coastguard Worker 116*9356374aSAndroid Build Coastguard Worker mutable Mutex mutex_; 117*9356374aSAndroid Build Coastguard Worker std::atomic<bool> notified_yet_; // written under mutex_ 118*9356374aSAndroid Build Coastguard Worker }; 119*9356374aSAndroid Build Coastguard Worker 120*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 121*9356374aSAndroid Build Coastguard Worker } // namespace absl 122*9356374aSAndroid Build Coastguard Worker 123*9356374aSAndroid Build Coastguard Worker #endif // ABSL_SYNCHRONIZATION_NOTIFICATION_H_ 124