userver: userver/engine/single_consumer_event.hpp Source File
Loading...
Searching...
No Matches
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