Ocean
Loading...
Searching...
No Matches
ScopedSubscription.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_BASE_SCOPED_SUBSCRIPTION_H
9#define META_OCEAN_BASE_SCOPED_SUBSCRIPTION_H
10
11#include "ocean/base/Base.h"
12#include "ocean/base/Lock.h"
13
14#include <functional>
15
16namespace Ocean
17{
18
19/**
20 * This class implements a subscription object which can be used unique subscriptions to e.g., callback functions.
21 * The subscription exists as long as the object exists.
22 * @tparam T The data type of the subscription id
23 * @tparam TOwner The data type of the class in which this subscription object will be defined
24 * @ingroup base
25 */
26template <typename T, typename TOwner>
28{
29 friend TOwner;
30
31 protected:
32
33 /**
34 * Definition of a callback function for release requests.
35 * @param subscriptionId The id of the subscription to be released
36 */
37 using ReleaseCallbackFunction = std::function<void(const T& subscriptionId)>;
38
39 public:
40
41 /**
42 * Creates an invalid (unsubscribed) subscription object.
43 */
45
46 /**
47 * Move constructor.
48 * @param scopedSubscription The object to be moved
49 */
51
52 /**
53 * Destructs the object and releases the subscription if any.
54 */
56
57 /**
58 * Explicitly releases the subscription before this object is disposes.
59 */
60 void release();
61
62 /**
63 * Returns whether this object holds a valid subscription.
64 * @return True, if so
65 */
66 inline bool isValid() const;
67
68 /**
69 * Returns whether this object holds a valid subscription.
70 * @return True, if so
71 */
72 explicit inline operator bool() const;
73
74 /**
75 * Move operator.
76 * @param scopedSubscription The object to be moved
77 * @return Reference to this object
78 */
80
81 /**
82 * Returns whether two subscription objects are identical.
83 * @param scopedSubscription The second subscription object to compare
84 * @return True, if so
85 */
86 inline bool operator==(const ScopedSubscriptionT<T, TOwner>& scopedSubscription) const;
87
88 /**
89 * Returns whether two subscription objects are not identical.
90 * @param scopedSubscription The second subscription object to compare
91 * @return True, if so
92 */
93 inline bool operator!=(const ScopedSubscriptionT<T, TOwner>& scopedSubscription) const;
94
95 /**
96 * Hash function.
97 * @param scopedSubscription The object for which the hash value will be determined
98 * @return The resulting hash value
99 */
100 inline size_t operator()(const ScopedSubscriptionT<T, TOwner>& scopedSubscription) const;
101
102 protected:
103
104 /**
105 * Disabled copy constructor.
106 * @param scopedSubscription The object which would be copied
107 */
108 ScopedSubscriptionT(const ScopedSubscriptionT<T, TOwner>& scopedSubscription) = delete;
109
110 /**
111 * Creates a new subscription object for a valid subscription id.
112 * @param subscriptionId The subscription id, must be valid
113 * @param releaseCallbackFunction The callback function which will be used when the subscription needs to be released, must be valid
114 */
115 explicit inline ScopedSubscriptionT(const T& subscriptionId, ReleaseCallbackFunction releaseCallbackFunction);
116
117 /**
118 * The disabled assign operator.
119 * @param scopedSubscription The object which would be assigned
120 * @return The reference to this object
121 */
123
124 protected:
125
126 /// The subscription id, nullptr if invalid.
127 std::unique_ptr<T> subscriptionId_ = nullptr;
128
129 /// The callback function which will be used when the subscription needs to be released.
131};
132
133/**
134 * This class implements the base class for all subscription handlers.
135 * @ingroup base
136 */
138{
139 public:
140
141 /**
142 * Definition of a scoped subscription object
143 */
145
146 protected:
147
148 /**
149 * Returns the subscription object for a given subscription id.
150 * @param subscriptionId The subscription id of the resulting subscription object
151 * @param releaseCallbackFunction The release function of the subscription, must be valid
152 * @return The subscription object
153 */
154 inline ScopedSubscriptionType scopedSubscription(const unsigned int& subscriptionId, ScopedSubscriptionType::ReleaseCallbackFunction releaseCallbackFunction);
155};
156
157/**
158 * This class implements a handler for scoped subscriptions to callback functions.
159 * The class mainly wraps a counter for subscription ids and a map holding the callback functions.
160 * @tparam TCallbackFunction The data type of the callback function
161 * @tparam TOwner The owner of this handler (the class in which the handler will be located)
162 * @tparam tThreadSafe True, to make the handler thread-safe
163 * @ingroup base
164 */
165template <typename TCallbackFunction, typename TOwner, bool tThreadSafe>
167{
168 friend TOwner;
169
170 public:
171
172 /**
173 * Definition of the data type of the callback function.
174 */
175 using CallbackFunctionType = TCallbackFunction;
176
177 /// True, if this handler is thread-safe.
178 static constexpr bool isThreadSafe_ = tThreadSafe;
179
180 protected:
181
182 /**
183 * Definition of an unordered map mapping subscription ids to callback functions.
184 */
185 using CallbackMap = std::unordered_map<unsigned int, TCallbackFunction>;
186
187 public:
188
189 /**
190 * Adds a new callback function to this handler.
191 * @param callbackFunction The callback function to add, must be valid
192 * @return The resulting scoped subscription object, the callback function will be in use until the resulting subscription object exists
193 */
194 [[nodiscard]] ScopedSubscriptionType addCallback(TCallbackFunction callbackFunction);
195
196 /**
197 * Returns the number of subscriptions.
198 * @return The handler's subscriptions
199 */
200 size_t subscriptions() const;
201
202 /**
203 * Returns whether no subscription exists.
204 * @return True, if so
205 */
206 bool isEmpty() const;
207
208 protected:
209
210 /**
211 * Calls all callback functions of this handler.
212 * @param args The arguments of the callback function
213 * @return The resulting of any of the callback functions
214 * @tparam TArgs The data types of the callback functions
215 */
216 template <class... TArgs>
217 typename TCallbackFunction::result_type callCallbacks(TArgs&& ... args);
218
219 /**
220 * Removes a callback function from the handler.
221 * @param subscriptionId The id of the subscription to be removed
222 */
223 void removeCallback(const unsigned int& subscriptionId);
224
225 protected:
226
227 /// The map mapping subscription ids to callback functions.
229
230 /// The counter for subscription ids.
231 unsigned int subscriptionIdCounter_ = 0u;
232
233 /// The optional lock object.
235};
236
237template <typename T, typename TOwner>
239{
240 *this = std::move(scopedSubscription);
241}
242
243template <typename T, typename TOwner>
244inline ScopedSubscriptionT<T, TOwner>::ScopedSubscriptionT(const T& subscriptionId, ReleaseCallbackFunction releaseCallbackFunction) :
245 subscriptionId_(std::make_unique<T>(subscriptionId)),
246 releaseCallbackFunction_(std::move(releaseCallbackFunction))
247{
248 ocean_assert(isValid());
249}
250
251template <typename T, typename TOwner>
256
257template <typename T, typename TOwner>
259{
260 if (subscriptionId_)
261 {
262 ocean_assert(releaseCallbackFunction_);
263 releaseCallbackFunction_(*subscriptionId_);
264
265 releaseCallbackFunction_ = nullptr;
266 subscriptionId_ = nullptr;
267 }
268}
269
270template <typename T, typename TOwner>
272{
273 return subscriptionId_ != nullptr;
274}
275
276template <typename T, typename TOwner>
278{
279 return isValid();
280}
281
282template <typename T, typename TOwner>
284{
285 if (this != &scopedSubscription)
286 {
287 release();
288
289 subscriptionId_ = std::move(scopedSubscription.subscriptionId_);
290 releaseCallbackFunction_ = std::move(scopedSubscription.releaseCallbackFunction_);
291 }
292
293 return *this;
294}
295
296template <typename T, typename TOwner>
298{
299 return subscriptionId_ == scopedSubscription.subscriptionId_ && releaseCallbackFunction_ == scopedSubscription.releaseCallbackFunction_;
300}
301
302template <typename T, typename TOwner>
304{
305 return !(*this == scopedSubscription);
306}
307
308template <typename T, typename TOwner>
310{
311 return std::hash<std::unique_ptr<T>>()(scopedSubscription.subscriptionId_);
312}
313
315{
316 ocean_assert(releaseCallbackFunction);
317 return ScopedSubscriptionType(subscriptionId, std::move(releaseCallbackFunction));
318}
319
320template <typename TCallbackFunction, typename TOwner, bool tThreadSafe>
322{
323 const TemplatedScopedLock<tThreadSafe> scopedLock(lock_);
324
325 const unsigned int subscriptionId = ++subscriptionIdCounter_;
326
327 ocean_assert(callbackMap_.find(subscriptionId) == callbackMap_.cend());
328 callbackMap_.emplace(subscriptionId, std::move(callbackFunction));
329
330 return scopedSubscription(subscriptionId, std::bind(&ScopedSubscriptionCallbackHandlerT<TCallbackFunction, TOwner, tThreadSafe>::removeCallback, this, std::placeholders::_1));
331}
332
333template <typename TCallbackFunction, typename TOwner, bool tThreadSafe>
335{
336 const TemplatedScopedLock<tThreadSafe> scopedLock(lock_);
337
338 return callbackMap_.size();
339}
340
341template <typename TCallbackFunction, typename TOwner, bool tThreadSafe>
343{
344 const TemplatedScopedLock<tThreadSafe> scopedLock(lock_);
345
346 return callbackMap_.empty();
347}
348
349template <typename TCallbackFunction, typename TOwner, bool tThreadSafe>
350template <class... TArgs>
352{
353 const TemplatedScopedLock<tThreadSafe> scopedLock(lock_);
354
355 for (typename CallbackMap::const_iterator iCallback = callbackMap_.cbegin(); iCallback != callbackMap_.cend(); ++iCallback)
356 {
357 const TCallbackFunction& callbackFunction = iCallback->second;
358
359 typename CallbackMap::const_iterator iNextCallback(iCallback);
360
361 if (++iNextCallback == callbackMap_.cend())
362 {
363 return callbackFunction(std::forward<TArgs>(args)...);
364 }
365 else
366 {
367 callbackFunction(std::forward<TArgs>(args)...);
368 }
369 }
370}
371
372template <typename TCallbackFunction, typename TOwner, bool tThreadSafe>
374{
375 const TemplatedScopedLock<tThreadSafe> scopedLock(lock_);
376
377 ocean_assert(callbackMap_.find(subscriptionId) != callbackMap_.cend());
378
379 callbackMap_.erase(subscriptionId);
380}
381
382}
383
384#endif // META_OCEAN_BASE_SCOPED_SUBSCRIPTION_H
This class implements a handler for scoped subscriptions to callback functions.
Definition ScopedSubscription.h:167
static constexpr bool isThreadSafe_
True, if this handler is thread-safe.
Definition ScopedSubscription.h:178
friend TOwner
Definition ScopedSubscription.h:168
unsigned int subscriptionIdCounter_
The counter for subscription ids.
Definition ScopedSubscription.h:231
TCallbackFunction CallbackFunctionType
Definition of the data type of the callback function.
Definition ScopedSubscription.h:175
void removeCallback(const unsigned int &subscriptionId)
Removes a callback function from the handler.
Definition ScopedSubscription.h:373
ScopedSubscriptionType addCallback(TCallbackFunction callbackFunction)
Adds a new callback function to this handler.
Definition ScopedSubscription.h:321
std::unordered_map< unsigned int, TCallbackFunction > CallbackMap
Definition of an unordered map mapping subscription ids to callback functions.
Definition ScopedSubscription.h:185
size_t subscriptions() const
Returns the number of subscriptions.
Definition ScopedSubscription.h:334
CallbackMap callbackMap_
The map mapping subscription ids to callback functions.
Definition ScopedSubscription.h:228
TemplatedLock< tThreadSafe > lock_
The optional lock object.
Definition ScopedSubscription.h:234
TCallbackFunction::result_type callCallbacks(TArgs &&... args)
Calls all callback functions of this handler.
Definition ScopedSubscription.h:351
bool isEmpty() const
Returns whether no subscription exists.
Definition ScopedSubscription.h:342
This class implements the base class for all subscription handlers.
Definition ScopedSubscription.h:138
ScopedSubscriptionT< unsigned int, ScopedSubscriptionHandler > ScopedSubscriptionType
Definition of a scoped subscription object.
Definition ScopedSubscription.h:144
ScopedSubscriptionType scopedSubscription(const unsigned int &subscriptionId, ScopedSubscriptionType::ReleaseCallbackFunction releaseCallbackFunction)
Returns the subscription object for a given subscription id.
Definition ScopedSubscription.h:314
This class implements a subscription object which can be used unique subscriptions to e....
Definition ScopedSubscription.h:28
bool operator==(const ScopedSubscriptionT< T, TOwner > &scopedSubscription) const
Returns whether two subscription objects are identical.
Definition ScopedSubscription.h:297
friend TOwner
Definition ScopedSubscription.h:29
ScopedSubscriptionT(ScopedSubscriptionT< T, TOwner > &&scopedSubscription)
Move constructor.
Definition ScopedSubscription.h:238
void release()
Explicitly releases the subscription before this object is disposes.
Definition ScopedSubscription.h:258
std::unique_ptr< T > subscriptionId_
The subscription id, nullptr if invalid.
Definition ScopedSubscription.h:127
std::function< void(const T &subscriptionId)> ReleaseCallbackFunction
Definition of a callback function for release requests.
Definition ScopedSubscription.h:37
size_t operator()(const ScopedSubscriptionT< T, TOwner > &scopedSubscription) const
Hash function.
Definition ScopedSubscription.h:309
ScopedSubscriptionT()=default
Creates an invalid (unsubscribed) subscription object.
ScopedSubscriptionT(const T &subscriptionId, ReleaseCallbackFunction releaseCallbackFunction)
Creates a new subscription object for a valid subscription id.
Definition ScopedSubscription.h:244
bool operator!=(const ScopedSubscriptionT< T, TOwner > &scopedSubscription) const
Returns whether two subscription objects are not identical.
Definition ScopedSubscription.h:303
bool isValid() const
Returns whether this object holds a valid subscription.
Definition ScopedSubscription.h:271
ScopedSubscriptionT< T, TOwner > & operator=(const ScopedSubscriptionT< T, TOwner > &scopedSubscription)=delete
The disabled assign operator.
ScopedSubscriptionT(const ScopedSubscriptionT< T, TOwner > &scopedSubscription)=delete
Disabled copy constructor.
~ScopedSubscriptionT()
Destructs the object and releases the subscription if any.
Definition ScopedSubscription.h:252
ReleaseCallbackFunction releaseCallbackFunction_
The callback function which will be used when the subscription needs to be released.
Definition ScopedSubscription.h:130
ScopedSubscriptionT< T, TOwner > & operator=(ScopedSubscriptionT< T, TOwner > &&scopedSubscription)
Move operator.
Definition ScopedSubscription.h:283
This class implements a template-based recursive lock object.
Definition Lock.h:99
This class implements a recursive scoped lock object that is activated by a boolean template paramete...
Definition Lock.h:178
The namespace covering the entire Ocean framework.
Definition Accessor.h:15