userver: userver/engine/single_consumer_event.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
single_consumer_event.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/single_consumer_event.hpp
4/// @brief @copybrief engine::SingleConsumerEvent
5
6#include <atomic>
7#include <chrono>
8
9#include <userver/engine/deadline.hpp>
10#include <userver/engine/impl/wait_list_fwd.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace engine {
15
16/// @ingroup userver_concurrency
17///
18/// @brief A multiple-producers, single-consumer event
19class SingleConsumerEvent final {
20 public:
21 struct NoAutoReset final {};
22
23 /// Creates an event that resets automatically on retrieval.
25
26 /// Creates an event that does not reset automatically.
27 explicit SingleConsumerEvent(NoAutoReset) noexcept;
28
29 SingleConsumerEvent(const SingleConsumerEvent&) = delete;
30 SingleConsumerEvent(SingleConsumerEvent&&) = delete;
31 SingleConsumerEvent& operator=(const SingleConsumerEvent&) = delete;
32 SingleConsumerEvent& operator=(SingleConsumerEvent&&) = delete;
33 ~SingleConsumerEvent();
34
35 /// @return whether this event resets automatically on retrieval
36 bool IsAutoReset() const noexcept;
37
38 /// @brief Waits until the event is in a signaled state.
39 ///
40 /// If the event is auto-resetting, clears the signal flag upon waking up. If
41 /// already in a signaled state, does the same without sleeping.
42 ///
43 /// If we the waiting failed (the event did not signal), because the optional
44 /// deadline is expired or the current task is cancelled, returns `false`.
45 ///
46 /// @return whether the event signaled
47 [[nodiscard]] bool WaitForEvent();
48
49 /// @overload bool WaitForEvent()
50 template <typename Clock, typename Duration>
51 [[nodiscard]] bool WaitForEventFor(std::chrono::duration<Clock, Duration>);
52
53 /// @overload bool WaitForEvent()
54 template <typename Clock, typename Duration>
55 [[nodiscard]] bool WaitForEventUntil(
56 std::chrono::time_point<Clock, Duration>);
57
58 /// @overload bool WaitForEvent()
59 [[nodiscard]] bool WaitForEventUntil(Deadline);
60
61 /// Resets the signal flag. Guarantees at least 'acquire' and 'release' memory
62 /// ordering. Must only be called by the waiting task.
63 void Reset() noexcept;
64
65 /// Sets the signal flag and wakes a coroutine that waits on it (if any).
66 /// If the signal flag is already set, does nothing.
67 ///
68 /// The waiter is allowed to destroy the SingleConsumerEvent immediately
69 /// after exiting WaitForEvent, ONLY IF the wait succeeded. Otherwise
70 /// a concurrent task may call Send on a destroyed SingleConsumerEvent.
71 /// Here is an example of this situation:
72 /// @snippet engine/single_consumer_event_test.cpp Wait and destroy
73 void Send();
74
75 /// Returns `true` iff already signaled. Never resets the signal.
76 [[nodiscard]] bool IsReady() const noexcept;
77
78 private:
79 class EventWaitStrategy;
80
81 bool GetIsSignaled() noexcept;
82
83 impl::FastPimplWaitListLight waiters_;
84 const bool is_auto_reset_{true};
85};
86
87template <typename Clock, typename Duration>
88bool SingleConsumerEvent::WaitForEventFor(
89 std::chrono::duration<Clock, Duration> duration) {
90 return WaitForEventUntil(Deadline::FromDuration(duration));
91}
92
93template <typename Clock, typename Duration>
94bool SingleConsumerEvent::WaitForEventUntil(
95 std::chrono::time_point<Clock, Duration> time_point) {
96 return WaitForEventUntil(Deadline::FromTimePoint(time_point));
97}
98
99} // namespace engine
100
101USERVER_NAMESPACE_END