Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:28

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // -----------------------------------------------------------------------------
0016 // notification.h
0017 // -----------------------------------------------------------------------------
0018 //
0019 // This header file defines a `Notification` abstraction, which allows threads
0020 // to receive notification of a single occurrence of a single event.
0021 //
0022 // The `Notification` object maintains a private boolean "notified" state that
0023 // transitions to `true` at most once. The `Notification` class provides the
0024 // following primary member functions:
0025 //   * `HasBeenNotified()` to query its state
0026 //   * `WaitForNotification*()` to have threads wait until the "notified" state
0027 //      is `true`.
0028 //   * `Notify()` to set the notification's "notified" state to `true` and
0029 //     notify all waiting threads that the event has occurred.
0030 //     This method may only be called once.
0031 //
0032 // Note that while `Notify()` may only be called once, it is perfectly valid to
0033 // call any of the `WaitForNotification*()` methods multiple times, from
0034 // multiple threads -- even after the notification's "notified" state has been
0035 // set -- in which case those methods will immediately return.
0036 //
0037 // Note that the lifetime of a `Notification` requires careful consideration;
0038 // it might not be safe to destroy a notification after calling `Notify()` since
0039 // it is still legal for other threads to call `WaitForNotification*()` methods
0040 // on the notification. However, observers responding to a "notified" state of
0041 // `true` can safely delete the notification without interfering with the call
0042 // to `Notify()` in the other thread.
0043 //
0044 // Memory ordering: For any threads X and Y, if X calls `Notify()`, then any
0045 // action taken by X before it calls `Notify()` is visible to thread Y after:
0046 //  * Y returns from `WaitForNotification()`, or
0047 //  * Y receives a `true` return value from either `HasBeenNotified()` or
0048 //    `WaitForNotificationWithTimeout()`.
0049 
0050 #ifndef ABSL_SYNCHRONIZATION_NOTIFICATION_H_
0051 #define ABSL_SYNCHRONIZATION_NOTIFICATION_H_
0052 
0053 #include <atomic>
0054 
0055 #include "absl/base/attributes.h"
0056 #include "absl/synchronization/mutex.h"
0057 #include "absl/time/time.h"
0058 
0059 namespace absl {
0060 ABSL_NAMESPACE_BEGIN
0061 
0062 // -----------------------------------------------------------------------------
0063 // Notification
0064 // -----------------------------------------------------------------------------
0065 class Notification {
0066  public:
0067   // Initializes the "notified" state to unnotified.
0068   Notification() : notified_yet_(false) {}
0069   explicit Notification(bool prenotify) : notified_yet_(prenotify) {}
0070   Notification(const Notification&) = delete;
0071   Notification& operator=(const Notification&) = delete;
0072   ~Notification();
0073 
0074   // Notification::HasBeenNotified()
0075   //
0076   // Returns the value of the notification's internal "notified" state.
0077   ABSL_MUST_USE_RESULT bool HasBeenNotified() const {
0078     return HasBeenNotifiedInternal(&this->notified_yet_);
0079   }
0080 
0081   // Notification::WaitForNotification()
0082   //
0083   // Blocks the calling thread until the notification's "notified" state is
0084   // `true`. Note that if `Notify()` has been previously called on this
0085   // notification, this function will immediately return.
0086   void WaitForNotification() const;
0087 
0088   // Notification::WaitForNotificationWithTimeout()
0089   //
0090   // Blocks until either the notification's "notified" state is `true` (which
0091   // may occur immediately) or the timeout has elapsed, returning the value of
0092   // its "notified" state in either case.
0093   bool WaitForNotificationWithTimeout(absl::Duration timeout) const;
0094 
0095   // Notification::WaitForNotificationWithDeadline()
0096   //
0097   // Blocks until either the notification's "notified" state is `true` (which
0098   // may occur immediately) or the deadline has expired, returning the value of
0099   // its "notified" state in either case.
0100   bool WaitForNotificationWithDeadline(absl::Time deadline) const;
0101 
0102   // Notification::Notify()
0103   //
0104   // Sets the "notified" state of this notification to `true` and wakes waiting
0105   // threads. Note: do not call `Notify()` multiple times on the same
0106   // `Notification`; calling `Notify()` more than once on the same notification
0107   // results in undefined behavior.
0108   void Notify();
0109 
0110  private:
0111   static inline bool HasBeenNotifiedInternal(
0112       const std::atomic<bool>* notified_yet) {
0113     return notified_yet->load(std::memory_order_acquire);
0114   }
0115 
0116   mutable Mutex mutex_;
0117   std::atomic<bool> notified_yet_;  // written under mutex_
0118 };
0119 
0120 ABSL_NAMESPACE_END
0121 }  // namespace absl
0122 
0123 #endif  // ABSL_SYNCHRONIZATION_NOTIFICATION_H_