userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
async_event_source.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/concurrent/async_event_source.hpp
4
/// @brief @copybrief concurrent::AsyncEventSource
5
6
#
include
<
cstddef
>
7
#
include
<
functional
>
8
#
include
<
string_view
>
9
#
include
<
typeinfo
>
10
#
include
<
utility
>
11
12
#
include
<
userver
/
utils
/
impl
/
internal_tag
.
hpp
>
13
14
USERVER_NAMESPACE_BEGIN
15
16
namespace
concurrent
{
17
18
class
FunctionId;
19
enum
class
UnsubscribingKind;
20
21
template
<
typename
... Args>
22
class
AsyncEventSource
;
23
24
namespace
impl {
25
26
class
AsyncEventSourceBase {
27
public
:
28
virtual
void
RemoveListener(FunctionId, UnsubscribingKind)
noexcept
= 0;
29
30
protected
:
31
// disallow deletion via pointer to base
32
~AsyncEventSourceBase();
33
};
34
35
}
// namespace impl
36
37
/// Uniquely identifies a subscription (usually the callback method owner) for
38
/// AsyncEventSource
39
class
FunctionId
final
{
40
public
:
41
constexpr
FunctionId() =
default
;
42
43
template
<
typename
Class>
44
explicit
FunctionId(Class* obj)
45
: FunctionId(obj,
typeid
(Class))
46
{}
47
48
explicit
operator
bool
()
const
;
49
50
bool
operator==(
const
FunctionId& other)
const
;
51
52
struct
Hash
final
{
53
std::size_t operator()(FunctionId id)
const
noexcept
;
54
};
55
56
private
:
57
FunctionId(
void
* ptr,
const
std::type_info& type);
58
59
void
* ptr_{
nullptr
};
60
const
std::type_info* type_{
nullptr
};
61
};
62
63
enum
class
UnsubscribingKind { kManual, kAutomatic };
64
65
/// @brief Manages the subscription to events from an AsyncEventSource
66
///
67
/// Removes the associated listener automatically on destruction.
68
///
69
/// The Scope is usually placed as a member in the subscribing object.
70
/// `Unsubscribe` should be called manually in the objects destructor, before
71
/// anything that the callback needs is destroyed.
72
class
[[nodiscard]] AsyncEventSubscriberScope
final
{
73
public
:
74
AsyncEventSubscriberScope() =
default
;
75
76
AsyncEventSubscriberScope(AsyncEventSubscriberScope&& scope)
noexcept
;
77
AsyncEventSubscriberScope& operator=(AsyncEventSubscriberScope&& other)
noexcept
;
78
~AsyncEventSubscriberScope();
79
80
/// Unsubscribes manually. The subscription should be cancelled before
81
/// anything that the callback needs is destroyed.
82
void
Unsubscribe
()
noexcept
;
83
84
/// @cond
85
// For internal use only.
86
template
<
typename
... Args>
87
AsyncEventSubscriberScope(
utils
::impl::InternalTag,
AsyncEventSource
<Args...>& channel, FunctionId id)
88
: AsyncEventSubscriberScope(
static_cast
<impl::AsyncEventSourceBase&>(channel), id)
89
{}
90
/// @endcond
91
92
private
:
93
AsyncEventSubscriberScope(impl::AsyncEventSourceBase& channel, FunctionId id);
94
95
impl::AsyncEventSourceBase* channel_{
nullptr
};
96
FunctionId id_;
97
};
98
99
/// @ingroup userver_concurrency
100
///
101
/// @brief The read-only side of an event channel. Events are delivered to
102
/// listeners in a strict FIFO order, i.e. only after the event was processed
103
/// a new event may appear for processing, same listener is never called
104
/// concurrently.
105
template
<
typename
... Args>
106
class
AsyncEventSource
:
public
impl::AsyncEventSourceBase {
107
public
:
108
using
Function = std::function<
void
(Args... args)>;
109
110
virtual
~AsyncEventSource() =
default
;
111
112
/// @brief Subscribes to updates from this event source
113
///
114
/// The listener won't be called immediately. To process the current value and
115
/// then listen to updates, use `UpdateAndListen` of specific event channels.
116
///
117
/// @warning Listeners should not be added or removed while processing the
118
/// event inside another listener.
119
///
120
/// Example usage:
121
/// @snippet concurrent/async_event_channel_test.cpp AddListener sample
122
///
123
/// @param obj the subscriber, which is the owner of the listener method, and
124
/// is also used as the unique identifier of the subscription for this
125
/// AsyncEventSource
126
/// @param name the name of the subscriber, for diagnostic purposes
127
/// @param func the listener method, usually called `On<DataName>Update`, e.g.
128
/// `OnConfigUpdate` or `OnCacheUpdate`
129
/// @returns a AsyncEventSubscriberScope controlling the subscription, which
130
/// should be stored as a member in the subscriber; `Unsubscribe` should be
131
/// called explicitly
132
template
<
class
Class>
133
AsyncEventSubscriberScope
AddListener
(Class* obj, std::string_view name,
void
(Class::*func)(Args...)) {
134
return
AddListener(FunctionId(obj), name, [obj, func](Args... args) { (obj->*func)(args...); });
135
}
136
137
/// @brief A type-erased version of AddListener
138
///
139
/// @param id the unique identifier of the subscription
140
/// @param name the name of the subscriber, for diagnostic purposes
141
/// @param func the callback used for event notifications
142
AsyncEventSubscriberScope
AddListener
(FunctionId id, std::string_view name, Function&& func) {
143
return
DoAddListener(id, name, std::move(func));
144
}
145
146
/// Used by AsyncEventSubscriberScope to cancel an event subscription
147
void
RemoveListener
(FunctionId, UnsubscribingKind)
noexcept
override
= 0;
148
149
protected
:
150
virtual
AsyncEventSubscriberScope DoAddListener(FunctionId id, std::string_view name, Function&& func) = 0;
151
};
152
153
}
// namespace concurrent
154
155
USERVER_NAMESPACE_END
userver
concurrent
async_event_source.hpp
Generated on
for userver by
Doxygen
1.17.0