You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+29-2Lines changed: 29 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,7 +39,7 @@ Synchronous and asynchronous delegates are available. Asynchronous variants hand
39
39
Remote delegates enable function invocation across processes or processors by using customizable serialization and transport mechanisms. All argument data is marshaled to support remote callable endpoints with any function signature. Minimal effort is required to extend support to any new library. Concrete examples are provided using support libraries below.
* **Transport:** [ZeroMQ](https://zeromq.org/), UDP, Data Pipe, memory buffer
42
+
* **Transport:** [ZeroMQ](https://zeromq.org/), UDP, data pipe, memory buffer
43
43
44
44
It is always safe to call the delegate. In its null state, a call will not perform any action and will return a default-constructed return value. A delegate behaves like a normal pointer type: it can be copied, compared for equality, called, and compared to `nullptr`. Const correctness is maintained; stored const objects can only be called by const member functions.
45
45
@@ -63,6 +63,12 @@ Typical use cases are:
63
63
64
64
The DelegateMQ library asynchronous features differ from `std::async` in that the caller-specified thread of control is used to invoke the target function bound to the delegate, rather than a random thread from the thread pool. The asynchronous variants copy the argument data into an event queue, ensuring safe transport to the destination thread, regardless of the argument type. This approach provides 'fire and forget' functionality, allowing the caller to avoid waiting or worrying about out-of-scope stack variables being accessed by the target thread.
65
65
66
+
DelegateMQ uses an external thread, transport, and serializer, all of which are based on simple, well-defined interfaces.
Originally published on CodeProject at: <a href="https://www.codeproject.com/Articles/5277036/Asynchronous-Multicast-Delegates-in-Modern-Cpluspl">Asynchronous Multicast Delegates in Modern C++</a>
67
73
68
74
# Documentation
@@ -81,11 +87,32 @@ Originally published on CodeProject at: <a href="https://www.codeproject.com/Art
81
87
82
88
See [Example Projects](docs/DETAILS.md#example-projects) to build other project examples.
83
89
90
+
# Features
91
+
92
+
DelegateMQ features at a glance.
93
+
94
+
| Feature | DelegateMQ |
95
+
| --- | --- |
96
+
| Purpose | DelegateMQ is a library used for invoking any callable synchronously, asynchronously, or remotely |
97
+
| Usages | Callbacks (synchronous and asynchronous), asynchronous API's, communication and data distribution, and more |
98
+
| Library | Allows customizing data sharing between threads, processes, or processors |
99
+
| Complexity | Lightweight and extensible through external library interfaces and full source code |
100
+
| Threading | No internal threads. External configurable thread interface portable to any OS (`IThread`). |
101
+
| Serialization | External configurable serialization data formats, such as MessagePack, RapidJSON, or custom encoding (`ISerializer`) |
102
+
| Transport | External configurable transport, such as ZeroMQ, TCP, UDP, serial, data pipe or any custom transport (`ITransport`) |
103
+
| Message Buffering | Provided by a communication library (e.g. ZeroMQ) or custom solution within transport |
104
+
| Timeouts and Retries | Provided by a communication library (e.g. ZeroMQ REQ-REP (Request-Reply)), TCP/IP stack, or custom solution |
105
+
| Dynamic Memory | Heap or DelegateMQ fixed-block allocator |
106
+
| Error Handling | Configurable for return error code, assert or exception |
107
+
| Embedded Friendly | Yes. Any OS such as Windows, Linux and FreeRTOS. An OS is not required (i.e. "superloop"). |
108
+
| Operation System | Any. Custom `IThread` implementation may be required. |
109
+
| Language | C++17 or higher |
110
+
84
111
# Related Repositories
85
112
86
113
## Alternative Implementations
87
114
88
-
Alternative asynchronous implementations similar in concept to C++ delegates, simpler, and less features.
115
+
Alternative asynchronous implementations similar in concept to DelegateMQ, simpler, and less features.
89
116
90
117
* <a href="https://github.com/endurodave/AsyncCallback">Asynchronous Callbacks in C++</a> - A C++ asynchronous callback framework.
91
118
* <a href="https://github.com/endurodave/C_AsyncCallback">Asynchronous Callbacks in C</a> - A C language asynchronous callback framework.
@@ -110,16 +112,11 @@ The DelegateMQ C++ library can invoke any callable function synchronously, async
110
112
111
113
[CMake](https://cmake.org/) is used to create the project files in the `build` directory. The repository root project executes all unit tests and examples with no external code or library dependencies.
112
114
113
-
`cmake -B build`
115
+
`cmake -B build .`
114
116
115
117
## Build Options
116
118
117
-
The build options are contained within the files below.
118
-
119
-
| File Name | Settings |
120
-
| --- | --- |
121
-
|`DelegateOpt.h`|`USE_ASSERTS` enable macro to use asserts instead of exceptions.<br>`USE_ALLOCATOR` enable macro to use a fixed-block allocator instead of the global heap. |
122
-
|`External.cmake`| Update directory locations for external libraries such as MessagePack, RapidJSON, ZeroMQ, and FreeRTOS. |
119
+
The DelegateMQ build options are located within `DelegateMQ.cmake`. Customize the external library paths using `External.cmake`.
123
120
124
121
## Example Projects
125
122
@@ -139,10 +136,53 @@ Some remote delegate example projects have external library dependencies. Follow
Add `DMQ_PREDEF_SOURCES` to your sources If using the predefined supporting DelegateMQ classes (e.g. `Thread`, `Serialize`, ...).
163
+
164
+
```
165
+
# Collect DelegateMQ predef source files
166
+
list(APPEND SOURCES ${DMQ_PREDEF_SOURCES})
167
+
```
168
+
169
+
Add the DelegateMQ include directory path.
170
+
171
+
```
172
+
include_directories(${DMQ_ROOT_DIR})
173
+
```
174
+
175
+
Add external library include paths defined within `External.cmake` as necessary.
176
+
177
+
```
178
+
include_directories(
179
+
${VCPKG_ROOT_DIR}/include
180
+
${MSGPACK_INCLUDE_DIR}
181
+
)
182
+
```
183
+
184
+
Include `DelegateMQ.h` to use the delegate library. Build and execute the project.
185
+
146
186
# Quick Start
147
187
148
188
## Basic Examples
@@ -901,7 +941,7 @@ In short, the DelegateMQ library offers features that are not natively available
901
941
902
942
# Library
903
943
904
-
A single include `DelegateMQ.h` provides access to all delegate library features. The library is wrapped within a `DelegateMQ` namespace. The table below shows the delegate class hierarchy.
944
+
A single include `DelegateMQ.h` provides access to all delegate library features. The library is wrapped within a `dmq` namespace. The table below shows the delegate class hierarchy.
905
945
906
946
```cpp
907
947
// Delegates
@@ -1091,7 +1131,7 @@ if (thread) {
1091
1131
`DispatchDelegate()` inserts a message into the thread message queue. `Thread` class uses a underlying `std::thread`. `Thread` is an implementation detail; create a unique `DispatchDelegate()` function based on the platform operating system API.
throw std::invalid_argument("Thread pointer is null");
@@ -1560,14 +1600,15 @@ See the `examples/sample-code` directory for additional examples.
1560
1600
1561
1601
## Sample Projects
1562
1602
1563
-
See the `examples/sample-projects` directory for example project. Most projects run on Windows or Linux. Others are Windows-only.
1603
+
See the `examples/sample-projects` directory for example project. Most projects run on Windows or Linux. Others are Windows-only. See [Examples Setup](#examples-setup) before running sample projects.
1564
1604
1565
1605
### bare-metal
1566
1606
1567
1607
Remote delegate example with no external libraries.
1568
1608
1569
1609
| Interface | Implementation |
1570
1610
| --- | --- |
1611
+
| `IThread` | `Thread` class implemented using `std::thread`.
1571
1612
| `ISerializer` | Insertion `operator<<` and extraction `operator>>` operators.
1572
1613
| `IDispatcher` | Shared sender/receiver `std::stringstream` for dispatcher transport.
1573
1614
@@ -1577,6 +1618,7 @@ Remote delegate example using FreeRTOS and no external libraries. Tested using t
1577
1618
1578
1619
| Interface | Implementation |
1579
1620
| --- | --- |
1621
+
| `IThread` | `Thread` class implemented using FreeRTOS.
1580
1622
| `ISerializer` | Insertion `operator<<` and extraction `operator>>` operators.
1581
1623
| `IDispatcher` | Shared sender/receiver `std::stringstream` for dispatcher transport.
1582
1624
@@ -1586,6 +1628,7 @@ Remote delegate example with Windows pipe and `serialize`.
1586
1628
1587
1629
| Interface | Implementation |
1588
1630
| --- | --- |
1631
+
| `IThread` | `Thread` class implemented using `std::thread`.
1589
1632
| `ISerializer` | `serialize` class.
1590
1633
| `IDispatcher` | Windows data pipe for dispatcher transport.
1591
1634
@@ -1595,6 +1638,7 @@ Remote delegate example with Windows UDP socket and `serialize`.
1595
1638
1596
1639
| Interface | Implementation |
1597
1640
| --- | --- |
1641
+
| `IThread` | `Thread` class implemented using `std::thread`.
1598
1642
| `ISerializer` | `serialize` class.
1599
1643
| `IDispatcher` | Windows UDP socket for dispatcher transport.
1600
1644
@@ -1604,6 +1648,7 @@ Remote delegate example using ZeroMQ and `serialize`.
1604
1648
1605
1649
| Interface | Implementation |
1606
1650
| --- | --- |
1651
+
| `IThread` | `Thread` class implemented using `std::thread`.
1607
1652
| `ISerializer` | `serialize` class.
1608
1653
| `IDispatcher` | ZeroMQ library for dispatcher transport.
1609
1654
@@ -1613,6 +1658,7 @@ Remote delegate example using ZeroMQ and MessagePack libraries.
1613
1658
1614
1659
| Interface | Implementation |
1615
1660
| --- | --- |
1661
+
| `IThread` | `Thread` class implemented using `std::thread`.
1616
1662
| `ISerializer` | MessagePack library.
1617
1663
| `IDispatcher` | ZeroMQ library for dispatcher transport.
1618
1664
@@ -1622,6 +1668,7 @@ Remote delegate example using ZeroMQ and RapidJSON libraries.
1622
1668
1623
1669
| Interface | Implementation |
1624
1670
| --- | --- |
1671
+
| `IThread` | `Thread` class implemented using `std::thread`.
1625
1672
| `ISerializer` | RapidJSON library.
1626
1673
| `IDispatcher` | ZeroMQ library for dispatcher transport.
1627
1674
@@ -1631,6 +1678,7 @@ Remote delegate example showing a complex system architecture using ZeroMQ and M
1631
1678
1632
1679
| Interface | Implementation |
1633
1680
| --- | --- |
1681
+
| `IThread` | `Thread` class implemented using `std::thread`.
1634
1682
| `ISerializer` | MessagePack library. |
1635
1683
| `IDispatcher` | ZeroMQ library for dispatcher transport. |
Copy file name to clipboardExpand all lines: docs/html/_async_invoke_8h_source.html
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -114,7 +114,7 @@
114
114
<divclass="line"><aid="l00028" name="l00028"></a><spanclass="lineno"> 28</span><spanclass="comment">// Is the calling function executing on the requested thread?</span></div>
<divclass="line"><aid="l00030" name="l00030"></a><spanclass="lineno"> 30</span><spanclass="comment">// Create a delegate that points to func to invoke on thread</span></div>
<divclass="line"><aid="l00033" name="l00033"></a><spanclass="lineno"> 33</span><spanclass="comment">// Invoke the delegate target function asynchronously and wait for function call to complete</span></div>
<divclass="line"><aid="l00068" name="l00068"></a><spanclass="lineno"> 68</span><spanclass="comment">// Is the calling function executing on the requested thread?</span></div>
<divclass="line"><aid="l00070" name="l00070"></a><spanclass="lineno"> 70</span><spanclass="comment">// Create a delegate that points to func to invoke on thread</span></div>
<divclass="line"><aid="l00073" name="l00073"></a><spanclass="lineno"> 73</span><spanclass="comment">// Invoke the delegate target function asynchronously and wait for function call to complete</span></div>
<divclass="ttc" id="aclass_thread_html_a2294b75a90c36b4f14e32ae8d975a0fb"><divclass="ttname"><ahref="class_thread.html#a2294b75a90c36b4f14e32ae8d975a0fb">Thread::GetThreadId</a></div><divclass="ttdeci">TaskHandle_t GetThreadId()</div><divclass="ttdoc">Get the ID of this thread instance.</div><divclass="ttdef"><b>Definition</b> freertos/Thread.cpp:51</div></div>
180
180
<divclass="ttc" id="aclass_thread_html_aafe48fc7ef98b9e6adcf7b188a30e35a"><divclass="ttname"><ahref="class_thread.html#aafe48fc7ef98b9e6adcf7b188a30e35a">Thread::GetCurrentThreadId</a></div><divclass="ttdeci">static TaskHandle_t GetCurrentThreadId()</div><divclass="ttdoc">Get the ID of the currently executing thread.</div><divclass="ttdef"><b>Definition</b> freertos/Thread.cpp:62</div></div>
181
-
<divclass="ttc" id="anamespace_delegate_m_q_html_a1087b41a3217d76f1744f5c83dbe9d72"><divclass="ttname"><ahref="namespace_delegate_m_q.html#a1087b41a3217d76f1744f5c83dbe9d72">DelegateMQ::MakeDelegate</a></div><divclass="ttdeci">auto MakeDelegate(RetType(*func)(Args... args))</div><divclass="ttdoc">Creates a delegate that binds to a free function.</div><divclass="ttdef"><b>Definition</b> Delegate.h:670</div></div>
181
+
<divclass="ttc" id="anamespacedmq_html_a65e308cc5f3e37d2f7f89c72b9744ae2"><divclass="ttname"><ahref="namespacedmq.html#a65e308cc5f3e37d2f7f89c72b9744ae2">dmq::MakeDelegate</a></div><divclass="ttdeci">auto MakeDelegate(RetType(*func)(Args... args))</div><divclass="ttdoc">Creates a delegate that binds to a free function.</div><divclass="ttdef"><b>Definition</b> Delegate.h:670</div></div>
0 commit comments