Skip to content

Commit 3cd0582

Browse files
committed
Update delegate library
1 parent 667b7b6 commit 3cd0582

10 files changed

Lines changed: 154 additions & 106 deletions

Delegate/Delegate.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class DelegateFree<RetType(Args...)> : public Delegate<RetType(Args...)> {
153153
m_func = rhs.m_func;
154154
}
155155

156-
/// @brief Invoke the bound delegate function synchronously.
156+
/// @brief Invoke the bound delegate function synchronously. Always safe to call.
157157
/// @param[in] args - the function arguments, if any.
158158
/// @return The bound function return value, if any. If empty delegate
159159
/// default return type returned.
@@ -363,7 +363,7 @@ class DelegateMember<TClass, RetType(Args...)> : public Delegate<RetType(Args...
363363
m_func = rhs.m_func;
364364
}
365365

366-
/// @brief Invoke the bound delegate function synchronously.
366+
/// @brief Invoke the bound delegate function synchronously. Always safe to call.
367367
/// @param[in] args - the function arguments, if any.
368368
/// @return The bound function return value, if any. If empty delegate
369369
/// default return type returned.
@@ -527,7 +527,12 @@ class DelegateFunction<RetType(Args...)> : public Delegate<RetType(Args...)> {
527527
/// @param[in] func The `std::function` to bind to the delegate. This function must
528528
/// match the signature of the delegate.
529529
void Bind(FunctionType func) {
530-
m_func = func;
530+
try {
531+
m_func = func;
532+
}
533+
catch (const std::bad_alloc&) {
534+
BAD_ALLOC();
535+
}
531536
}
532537

533538
/// Compares two ClassType objects using the '<' operator.
@@ -555,7 +560,7 @@ class DelegateFunction<RetType(Args...)> : public Delegate<RetType(Args...)> {
555560
m_func = rhs.m_func;
556561
}
557562

558-
/// @brief Invoke the bound delegate function synchronously.
563+
/// @brief Invoke the bound delegate function synchronously. Always safe to call.
559564
/// @param[in] args - the function arguments, if any.
560565
/// @return The bound function return value, if any. If empty delegate
561566
/// default return type returned.

Delegate/DelegateAsync.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class DelegateFreeAsync<RetType(Args...)> : public DelegateFree<RetType(Args...)
146146
/// and copying the state of the current object to it.
147147
/// @return A pointer to a new `ClassType` instance.
148148
/// @post The caller is responsible for deleting the clone object.
149-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
149+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
150150
virtual ClassType* Clone() const override {
151151
return new(std::nothrow) ClassType(*this);
152152
}
@@ -220,7 +220,7 @@ class DelegateFreeAsync<RetType(Args...)> : public DelegateFree<RetType(Args...)
220220
/// @details Invoke delegate function asynchronously and do not wait for return value.
221221
/// This function is called by the source thread. Dispatches the delegate data into the
222222
/// destination thread message queue. `Invoke()` must be called by the destination
223-
/// thread to invoke the target function.
223+
/// thread to invoke the target function. Always safe to call.
224224
///
225225
/// The `DelegateAsyncMsg` duplicates and copies the function arguments into heap memory.
226226
/// The source thread is not required to place function arguments into the heap. The delegate
@@ -230,7 +230,7 @@ class DelegateFreeAsync<RetType(Args...)> : public DelegateFree<RetType(Args...)
230230
/// @return A default return value. The return value is *not* returned from the
231231
/// target function. Do not use the return value.
232232
/// @post Do not use the return value as its not valid.
233-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
233+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
234234
virtual RetType operator()(Args... args) override {
235235
if (this->Empty())
236236
return RetType();
@@ -272,7 +272,7 @@ class DelegateFreeAsync<RetType(Args...)> : public DelegateFree<RetType(Args...)
272272
}
273273

274274
/// @brief Invoke delegate function asynchronously. Do not wait for return value.
275-
/// Called by the source thread.
275+
/// Called by the source thread. Always safe to call.
276276
/// @param[in] args The function arguments, if any.
277277
void AsyncInvoke(Args... args) {
278278
operator()(std::forward<Args>(args)...);
@@ -446,7 +446,7 @@ class DelegateMemberAsync<TClass, RetType(Args...)> : public DelegateMember<TCla
446446
/// and copying the state of the current object to it.
447447
/// @return A pointer to a new `ClassType` instance.
448448
/// @post The caller is responsible for deleting the clone object.
449-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
449+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
450450
virtual ClassType* Clone() const override {
451451
return new(std::nothrow) ClassType(*this);
452452
}
@@ -520,7 +520,7 @@ class DelegateMemberAsync<TClass, RetType(Args...)> : public DelegateMember<TCla
520520
/// @details Invoke delegate function asynchronously and do not wait for return value.
521521
/// This function is called by the source thread. Dispatches the delegate data into the
522522
/// destination thread message queue. `Invoke()` must be called by the destination
523-
/// thread to invoke the target function.
523+
/// thread to invoke the target function. Always safe to call.
524524
///
525525
/// The `DelegateAsyncMsg` duplicates and copies the function arguments into heap memory.
526526
/// The source thread is not required to place function arguments into the heap. The delegate
@@ -530,7 +530,7 @@ class DelegateMemberAsync<TClass, RetType(Args...)> : public DelegateMember<TCla
530530
/// @return A default return value. The return value is *not* returned from the
531531
/// target function. Do not use the return value.
532532
/// @post Do not use the return value as its not valid.
533-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
533+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
534534
virtual RetType operator()(Args... args) override {
535535
if (this->Empty())
536536
return RetType();
@@ -572,7 +572,7 @@ class DelegateMemberAsync<TClass, RetType(Args...)> : public DelegateMember<TCla
572572
}
573573

574574
/// @brief Invoke delegate function asynchronously. Do not wait for return value.
575-
/// Called by the source thread.
575+
/// Called by the source thread. Always safe to call.
576576
/// @param[in] args The function arguments, if any.
577577
void AsyncInvoke(Args... args) {
578578
operator()(std::forward<Args>(args)...);
@@ -687,7 +687,7 @@ class DelegateFunctionAsync<RetType(Args...)> : public DelegateFunction<RetType(
687687
/// and copying the state of the current object to it.
688688
/// @return A pointer to a new `ClassType` instance.
689689
/// @post The caller is responsible for deleting the clone object.
690-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
690+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
691691
virtual ClassType* Clone() const override {
692692
return new(std::nothrow) ClassType(*this);
693693
}
@@ -761,7 +761,7 @@ class DelegateFunctionAsync<RetType(Args...)> : public DelegateFunction<RetType(
761761
/// @details Invoke delegate function asynchronously and do not wait for return value.
762762
/// This function is called by the source thread. Dispatches the delegate data into the
763763
/// destination thread message queue. `Invoke()` must be called by the destination
764-
/// thread to invoke the target function.
764+
/// thread to invoke the target function. Always safe to call.
765765
///
766766
/// The `DelegateAsyncMsg` duplicates and copies the function arguments into heap memory.
767767
/// The source thread is not required to place function arguments into the heap. The delegate
@@ -771,7 +771,7 @@ class DelegateFunctionAsync<RetType(Args...)> : public DelegateFunction<RetType(
771771
/// @return A default return value. The return value is *not* returned from the
772772
/// target function. Do not use the return value.
773773
/// @post Do not use the return value as its not valid.
774-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
774+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
775775
virtual RetType operator()(Args... args) override {
776776
if (this->Empty())
777777
return RetType();
@@ -813,7 +813,7 @@ class DelegateFunctionAsync<RetType(Args...)> : public DelegateFunction<RetType(
813813
}
814814

815815
/// @brief Invoke delegate function asynchronously. Do not wait for return value.
816-
/// Called by the source thread.
816+
/// Called by the source thread. Always safe to call.
817817
/// @param[in] args The function arguments, if any.
818818
void AsyncInvoke(Args... args) {
819819
operator()(std::forward<Args>(args)...);

Delegate/DelegateAsyncWait.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ class DelegateFreeAsyncWait<RetType(Args...)> : public DelegateFree<RetType(Args
193193
/// and copying the state of the current object to it.
194194
/// @return A pointer to a new `ClassType` instance.
195195
/// @post The caller is responsible for deleting the clone object.
196-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
196+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
197197
virtual ClassType* Clone() const override {
198198
return new(std::nothrow) ClassType(*this);
199199
}
@@ -272,7 +272,7 @@ class DelegateFreeAsyncWait<RetType(Args...)> : public DelegateFree<RetType(Args
272272
/// @details Invoke delegate function asynchronously and wait for the return value.
273273
/// This function is called by the source thread. Dispatches the delegate data into the
274274
/// destination thread message queue. `Invoke()` must be called by the destination
275-
/// thread to invoke the target function.
275+
/// thread to invoke the target function. Always safe to call.
276276
///
277277
/// If the destination thread invokes the function within `m_timeout`, the return
278278
/// value is obtained from the destination thread function call. If `m_timeout` expires
@@ -340,7 +340,7 @@ class DelegateFreeAsyncWait<RetType(Args...)> : public DelegateFree<RetType(Args
340340
}
341341

342342
/// @brief Invoke delegate function asynchronously and block for function return value.
343-
/// Called by the source thread.
343+
/// Called by the source thread. Always safe to call.
344344
/// @param[in] args The function arguments, if any.
345345
/// @return The bound function return value stored withing `std::optional`. Use
346346
/// `has_value()` to check if the the return value is valid. `value()` contains
@@ -596,7 +596,7 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
596596
/// and copying the state of the current object to it.
597597
/// @return A pointer to a new `ClassType` instance.
598598
/// @post The caller is responsible for deleting the clone object.
599-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
599+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
600600
virtual ClassType* Clone() const override {
601601
return new(std::nothrow) ClassType(*this);
602602
}
@@ -675,7 +675,7 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
675675
/// @details Invoke delegate function asynchronously and wait for the return value.
676676
/// This function is called by the source thread. Dispatches the delegate data into the
677677
/// destination thread message queue. `Invoke()` must be called by the destination
678-
/// thread to invoke the target function.
678+
/// thread to invoke the target function. Always safe to call.
679679
///
680680
/// If the destination thread invokes the function within `m_timeout`, the return
681681
/// value is obtained from the destination thread function call. If `m_timeout` expires
@@ -743,7 +743,7 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
743743
}
744744

745745
/// @brief Invoke delegate function asynchronously and block for function return value.
746-
/// Called by the source thread.
746+
/// Called by the source thread. Always safe to call.
747747
/// @param[in] args The function arguments, if any.
748748
/// @return The bound function return value stored withing `std::optional`. Use
749749
/// `has_value()` to check if the the return value is valid. `value()` contains
@@ -918,7 +918,7 @@ class DelegateFunctionAsyncWait<RetType(Args...)> : public DelegateFunction<RetT
918918
/// and copying the state of the current object to it.
919919
/// @return A pointer to a new `ClassType` instance.
920920
/// @post The caller is responsible for deleting the clone object.
921-
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS no defined.
921+
/// @throws std::bad_alloc If dynamic memory allocation fails and USE_ASSERTS not defined.
922922
virtual ClassType* Clone() const override {
923923
return new(std::nothrow) ClassType(*this);
924924
}
@@ -997,7 +997,7 @@ class DelegateFunctionAsyncWait<RetType(Args...)> : public DelegateFunction<RetT
997997
/// @details Invoke delegate function asynchronously and wait for the return value.
998998
/// This function is called by the source thread. Dispatches the delegate data into the
999999
/// destination thread message queue. `Invoke()` must be called by the destination
1000-
/// thread to invoke the target function.
1000+
/// thread to invoke the target function. Always safe to call.
10011001
///
10021002
/// If the destination thread invokes the function within `m_timeout`, the return
10031003
/// value is obtained from the destination thread function call. If `m_timeout` expires
@@ -1065,7 +1065,7 @@ class DelegateFunctionAsyncWait<RetType(Args...)> : public DelegateFunction<RetT
10651065
}
10661066

10671067
/// @brief Invoke delegate function asynchronously and block for function return value.
1068-
/// Called by the source thread.
1068+
/// Called by the source thread. Always safe to call.
10691069
/// @param[in] args The function arguments, if any.
10701070
/// @return The bound function return value stored withing `std::optional`. Use
10711071
/// `has_value()` to check if the the return value is valid. `value()` contains

Delegate/DelegateLib.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,24 @@
3131
///
3232
/// Typical use cases are:
3333
///
34-
/// * Publish / Subscribe(Event - Driven Programming)
35-
/// * Thread - Safe Asynchronous API(Subsystem / Library)
36-
/// * Anonymous Thread - Safe Callbacks on Specified Thread
34+
/// * Asynchronous Method Invocation(AMI)
35+
/// * Publish / Subscribe(Observer) Pattern
36+
/// * Anonymous, Asynchronous Thread - Safe Callbacks
37+
/// * Event - Driven Programming
38+
/// * Thread - Safe Asynchronous API
39+
/// * Design Patterns(Active Object)
3740
///
38-
/// The delegate library differs from `std::async` in that the caller-specified thread of
39-
/// control is used to invoke the target function bound to the delegate. The asynchronous
41+
/// The delegate library's asynchronous features differ from `std::async` in that the
42+
/// caller-specified thread of control is used to invoke the target function bound to
43+
/// the delegate, rather than a random thread from the thread pool. The asynchronous
4044
/// variants copy the argument data into the event queue, ensuring safe transport to the
41-
/// destination thread, regardless of the argument type. This approach offers 'fire and forget'
42-
/// functionality without the caller waiting.
45+
/// destination thread, regardless of the argument type. This approach provides 'fire and
46+
/// forget' functionality, allowing the caller to avoid waiting or worrying about
47+
/// out-of-scope stack variables being accessed by the target thread.
4348
///
44-
/// The `Async` and `AsyncWait` class variants may throw `std::alloc` if heap allocation
45-
/// fails within `operator()(Args... args)`. All other delegate class functions do not throw
46-
/// exceptions.
49+
/// The `Async` and `AsyncWait` class variants may throw `std::bad_alloc` if heap allocation
50+
/// fails within `operator()(Args... args)`. Alternatively, define `USE_ASSERTS` to use `assert`
51+
/// as opposed to exceptions. All other delegate class functions do not throw exceptions.
4752
///
4853
/// Github responsitory location:
4954
/// https://github.com/endurodave/cpp-async-delegate

Delegate/DelegateOpt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/// @brief Delegate library options header file.
66

77
// Define this macro to switch between assert or exception handling
8-
//#define USE_ASSERTS // Comment this out to use exceptions
8+
//#define USE_ASSERTS // Comment this out to use asserts
99

1010
#ifdef USE_ASSERTS
1111
#include <cassert>

0 commit comments

Comments
 (0)