Skip to content

Commit 0ea731c

Browse files
committed
Update documentation
1 parent 0edbaee commit 0ea731c

File tree

371 files changed

+37434
-5091
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

371 files changed

+37434
-5091
lines changed

README.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Synchronous and asynchronous delegates are available. Asynchronous variants hand
3939
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.
4040
4141
* **Serialization:** [MessagePack](https://msgpack.org/index.html), [RapidJSON](https://github.com/Tencent/rapidjson), [MessageSerialize](https://github.com/endurodave/MessageSerialize)
42-
* **Transport:** [ZeroMQ](https://zeromq.org/), UDP, Data Pipe, memory buffer
42+
* **Transport:** [ZeroMQ](https://zeromq.org/), UDP, data pipe, memory buffer
4343
4444
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.
4545
@@ -63,6 +63,12 @@ Typical use cases are:
6363
6464
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.
6565
66+
DelegateMQ uses an external thread, transport, and serializer, all of which are based on simple, well-defined interfaces.
67+
68+
<img src="docs/LayerDiagram.jpg" alt="DelegateMQ Layer Diagram" style="width:60%;"><br>
69+
*DelegateMQ Layer Diagram*
70+
71+
6672
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>
6773
6874
# Documentation
@@ -81,11 +87,32 @@ Originally published on CodeProject at: <a href="https://www.codeproject.com/Art
8187
8288
See [Example Projects](docs/DETAILS.md#example-projects) to build other project examples.
8389
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+
84111
# Related Repositories
85112
86113
## Alternative Implementations
87114
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.
89116
90117
* <a href="https://github.com/endurodave/AsyncCallback">Asynchronous Callbacks in C++</a> - A C++ asynchronous callback framework.
91118
* <a href="https://github.com/endurodave/C_AsyncCallback">Asynchronous Callbacks in C</a> - A C language asynchronous callback framework.

docs/DETAILS.md

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
[![conan Ubuntu](https://github.com/endurodave/cpp-async-delegate/actions/workflows/cmake_ubuntu.yml/badge.svg)](https://github.com/endurodave/cpp-async-delegate/actions/workflows/cmake_ubuntu.yml)
33
[![conan Ubuntu](https://github.com/endurodave/cpp-async-delegate/actions/workflows/cmake_clang.yml/badge.svg)](https://github.com/endurodave/cpp-async-delegate/actions/workflows/cmake_clang.yml)
44
[![conan Windows](https://github.com/endurodave/cpp-async-delegate/actions/workflows/cmake_windows.yml/badge.svg)](https://github.com/endurodave/cpp-async-delegate/actions/workflows/cmake_windows.yml)
5+
[![Codecov](https://codecov.io/gh/endurodave/cpp-async-delegate/branch/master/graph/badge.svg)](https://app.codecov.io/gh/endurodave/cpp-async-delegate)
56

67
# Delegates in C++
78

@@ -16,6 +17,7 @@ The DelegateMQ C++ library can invoke any callable function synchronously, async
1617
- [Build Options](#build-options)
1718
- [Example Projects](#example-projects)
1819
- [Examples Setup](#examples-setup)
20+
- [Build Integration](#build-integration)
1921
- [Quick Start](#quick-start)
2022
- [Basic Examples](#basic-examples)
2123
- [Publish/Subscribe Example](#publishsubscribe-example)
@@ -110,16 +112,11 @@ The DelegateMQ C++ library can invoke any callable function synchronously, async
110112

111113
[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.
112114

113-
`cmake -B build`
115+
`cmake -B build .`
114116

115117
## Build Options
116118

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`.
123120

124121
## Example Projects
125122

@@ -139,10 +136,53 @@ Some remote delegate example projects have external library dependencies. Follow
139136
6. Clone [FreeRTOS](https://github.com/FreeRTOS/FreeRTOS).
140137
7. Edit DelegateMQ `External.cmake` file and update external library directory locations.
141138
9. Build any example subproject within the `example/sample-projects` directory.<br>
142-
`cmake -B build`
139+
`cmake -B build .`
143140

144141
See [Sample Projects](#sample-projects) for details regarding each sample project.
145142

143+
## Build Integration
144+
145+
Follow these steps to integrate DelegateMQ into a project.
146+
147+
Set the desired DMQ options and include `DelegateMQ.cmake` within your `CMakeLists.txt` file.
148+
149+
```
150+
# Set build options
151+
set (DMQ_EXTERNAL_LIB "ON")
152+
set (DMQ_ALLOCATOR "OFF")
153+
set (DMQ_UTIL "ON")
154+
set (DMQ_THREAD "DMQ_THREAD_STDLIB")
155+
set (DMQ_SERIALIZE "DMQ_SERIALIZE_MSGPACK")
156+
set (DMQ_TRANSPORT "DMQ_TRANSPORT_ZEROMQ")
157+
include("${CMAKE_SOURCE_DIR}/../../../../src/delegate-mq/DelegateMQ.cmake")
158+
```
159+
160+
Update `External.cmake` external library paths.
161+
162+
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+
146186
# Quick Start
147187

148188
## Basic Examples
@@ -901,7 +941,7 @@ In short, the DelegateMQ library offers features that are not natively available
901941

902942
# Library
903943

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.
905945

906946
```cpp
907947
// Delegates
@@ -1091,7 +1131,7 @@ if (thread) {
10911131
`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.
10921132

10931133
```cpp
1094-
void Thread::DispatchDelegate(std::shared_ptr<DelegateMQ::DelegateMsg> msg)
1134+
void Thread::DispatchDelegate(std::shared_ptr<dmq::DelegateMsg> msg)
10951135
{
10961136
if (m_thread == nullptr)
10971137
throw std::invalid_argument("Thread pointer is null");
@@ -1560,14 +1600,15 @@ See the `examples/sample-code` directory for additional examples.
15601600
15611601
## Sample Projects
15621602
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.
15641604
15651605
### bare-metal
15661606
15671607
Remote delegate example with no external libraries.
15681608
15691609
| Interface | Implementation |
15701610
| --- | --- |
1611+
| `IThread` | `Thread` class implemented using `std::thread`.
15711612
| `ISerializer` | Insertion `operator<<` and extraction `operator>>` operators.
15721613
| `IDispatcher` | Shared sender/receiver `std::stringstream` for dispatcher transport.
15731614
@@ -1577,6 +1618,7 @@ Remote delegate example using FreeRTOS and no external libraries. Tested using t
15771618
15781619
| Interface | Implementation |
15791620
| --- | --- |
1621+
| `IThread` | `Thread` class implemented using FreeRTOS.
15801622
| `ISerializer` | Insertion `operator<<` and extraction `operator>>` operators.
15811623
| `IDispatcher` | Shared sender/receiver `std::stringstream` for dispatcher transport.
15821624
@@ -1586,6 +1628,7 @@ Remote delegate example with Windows pipe and `serialize`.
15861628
15871629
| Interface | Implementation |
15881630
| --- | --- |
1631+
| `IThread` | `Thread` class implemented using `std::thread`.
15891632
| `ISerializer` | `serialize` class.
15901633
| `IDispatcher` | Windows data pipe for dispatcher transport.
15911634
@@ -1595,6 +1638,7 @@ Remote delegate example with Windows UDP socket and `serialize`.
15951638
15961639
| Interface | Implementation |
15971640
| --- | --- |
1641+
| `IThread` | `Thread` class implemented using `std::thread`.
15981642
| `ISerializer` | `serialize` class.
15991643
| `IDispatcher` | Windows UDP socket for dispatcher transport.
16001644
@@ -1604,6 +1648,7 @@ Remote delegate example using ZeroMQ and `serialize`.
16041648
16051649
| Interface | Implementation |
16061650
| --- | --- |
1651+
| `IThread` | `Thread` class implemented using `std::thread`.
16071652
| `ISerializer` | `serialize` class.
16081653
| `IDispatcher` | ZeroMQ library for dispatcher transport.
16091654
@@ -1613,6 +1658,7 @@ Remote delegate example using ZeroMQ and MessagePack libraries.
16131658
16141659
| Interface | Implementation |
16151660
| --- | --- |
1661+
| `IThread` | `Thread` class implemented using `std::thread`.
16161662
| `ISerializer` | MessagePack library.
16171663
| `IDispatcher` | ZeroMQ library for dispatcher transport.
16181664
@@ -1622,6 +1668,7 @@ Remote delegate example using ZeroMQ and RapidJSON libraries.
16221668
16231669
| Interface | Implementation |
16241670
| --- | --- |
1671+
| `IThread` | `Thread` class implemented using `std::thread`.
16251672
| `ISerializer` | RapidJSON library.
16261673
| `IDispatcher` | ZeroMQ library for dispatcher transport.
16271674
@@ -1631,6 +1678,7 @@ Remote delegate example showing a complex system architecture using ZeroMQ and M
16311678
16321679
| Interface | Implementation |
16331680
| --- | --- |
1681+
| `IThread` | `Thread` class implemented using `std::thread`.
16341682
| `ISerializer` | MessagePack library. |
16351683
| `IDispatcher` | ZeroMQ library for dispatcher transport. |
16361684

docs/LayerDiagram.jpg

38.7 KB
Loading

docs/html/_async_invoke_8h_source.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
<div class="line"><a id="l00028" name="l00028"></a><span class="lineno"> 28</span> <span class="comment">// Is the calling function executing on the requested thread?</span></div>
115115
<div class="line"><a id="l00029" name="l00029"></a><span class="lineno"> 29</span> <span class="keywordflow">if</span> (thread.<a class="code hl_function" href="class_thread.html#a2294b75a90c36b4f14e32ae8d975a0fb">GetThreadId</a>() != <a class="code hl_function" href="class_thread.html#aafe48fc7ef98b9e6adcf7b188a30e35a">Thread::GetCurrentThreadId</a>()) {</div>
116116
<div class="line"><a id="l00030" name="l00030"></a><span class="lineno"> 30</span> <span class="comment">// Create a delegate that points to func to invoke on thread</span></div>
117-
<div class="line"><a id="l00031" name="l00031"></a><span class="lineno"> 31</span> <span class="keyword">auto</span> delegate = <a class="code hl_function" href="namespace_delegate_m_q.html#a1087b41a3217d76f1744f5c83dbe9d72">DelegateMQ::MakeDelegate</a>(func, thread, timeout);</div>
117+
<div class="line"><a id="l00031" name="l00031"></a><span class="lineno"> 31</span> <span class="keyword">auto</span> delegate = <a class="code hl_function" href="namespacedmq.html#a65e308cc5f3e37d2f7f89c72b9744ae2">dmq::MakeDelegate</a>(func, thread, timeout);</div>
118118
<div class="line"><a id="l00032" name="l00032"></a><span class="lineno"> 32</span> </div>
119119
<div class="line"><a id="l00033" name="l00033"></a><span class="lineno"> 33</span> <span class="comment">// Invoke the delegate target function asynchronously and wait for function call to complete</span></div>
120120
<div class="line"><a id="l00034" name="l00034"></a><span class="lineno"> 34</span> <span class="keyword">auto</span> retVal = delegate.AsyncInvoke(std::forward&lt;Args&gt;(args)...);</div>
@@ -147,7 +147,7 @@
147147
<div class="line"><a id="l00068" name="l00068"></a><span class="lineno"> 68</span> <span class="comment">// Is the calling function executing on the requested thread?</span></div>
148148
<div class="line"><a id="l00069" name="l00069"></a><span class="lineno"> 69</span> <span class="keywordflow">if</span> (thread.<a class="code hl_function" href="class_thread.html#a2294b75a90c36b4f14e32ae8d975a0fb">GetThreadId</a>() != <a class="code hl_function" href="class_thread.html#aafe48fc7ef98b9e6adcf7b188a30e35a">Thread::GetCurrentThreadId</a>()) {</div>
149149
<div class="line"><a id="l00070" name="l00070"></a><span class="lineno"> 70</span> <span class="comment">// Create a delegate that points to func to invoke on thread</span></div>
150-
<div class="line"><a id="l00071" name="l00071"></a><span class="lineno"> 71</span> <span class="keyword">auto</span> delegate = <a class="code hl_function" href="namespace_delegate_m_q.html#a1087b41a3217d76f1744f5c83dbe9d72">DelegateMQ::MakeDelegate</a>(tclass, func, thread, timeout);</div>
150+
<div class="line"><a id="l00071" name="l00071"></a><span class="lineno"> 71</span> <span class="keyword">auto</span> delegate = <a class="code hl_function" href="namespacedmq.html#a65e308cc5f3e37d2f7f89c72b9744ae2">dmq::MakeDelegate</a>(tclass, func, thread, timeout);</div>
151151
<div class="line"><a id="l00072" name="l00072"></a><span class="lineno"> 72</span> </div>
152152
<div class="line"><a id="l00073" name="l00073"></a><span class="lineno"> 73</span> <span class="comment">// Invoke the delegate target function asynchronously and wait for function call to complete</span></div>
153153
<div class="line"><a id="l00074" name="l00074"></a><span class="lineno"> 74</span> <span class="keyword">auto</span> retVal = delegate.AsyncInvoke(std::forward&lt;Args&gt;(args)...);</div>
@@ -178,7 +178,7 @@
178178
<div class="ttc" id="aclass_thread_html"><div class="ttname"><a href="class_thread.html">Thread</a></div><div class="ttdef"><b>Definition</b> freertos/Thread.h:19</div></div>
179179
<div class="ttc" id="aclass_thread_html_a2294b75a90c36b4f14e32ae8d975a0fb"><div class="ttname"><a href="class_thread.html#a2294b75a90c36b4f14e32ae8d975a0fb">Thread::GetThreadId</a></div><div class="ttdeci">TaskHandle_t GetThreadId()</div><div class="ttdoc">Get the ID of this thread instance.</div><div class="ttdef"><b>Definition</b> freertos/Thread.cpp:51</div></div>
180180
<div class="ttc" id="aclass_thread_html_aafe48fc7ef98b9e6adcf7b188a30e35a"><div class="ttname"><a href="class_thread.html#aafe48fc7ef98b9e6adcf7b188a30e35a">Thread::GetCurrentThreadId</a></div><div class="ttdeci">static TaskHandle_t GetCurrentThreadId()</div><div class="ttdoc">Get the ID of the currently executing thread.</div><div class="ttdef"><b>Definition</b> freertos/Thread.cpp:62</div></div>
181-
<div class="ttc" id="anamespace_delegate_m_q_html_a1087b41a3217d76f1744f5c83dbe9d72"><div class="ttname"><a href="namespace_delegate_m_q.html#a1087b41a3217d76f1744f5c83dbe9d72">DelegateMQ::MakeDelegate</a></div><div class="ttdeci">auto MakeDelegate(RetType(*func)(Args... args))</div><div class="ttdoc">Creates a delegate that binds to a free function.</div><div class="ttdef"><b>Definition</b> Delegate.h:670</div></div>
181+
<div class="ttc" id="anamespacedmq_html_a65e308cc5f3e37d2f7f89c72b9744ae2"><div class="ttname"><a href="namespacedmq.html#a65e308cc5f3e37d2f7f89c72b9744ae2">dmq::MakeDelegate</a></div><div class="ttdeci">auto MakeDelegate(RetType(*func)(Args... args))</div><div class="ttdoc">Creates a delegate that binds to a free function.</div><div class="ttdef"><b>Definition</b> Delegate.h:670</div></div>
182182
</div><!-- fragment --></div><!-- contents -->
183183
</div><!-- doc-content -->
184184
<!-- start footer part -->

0 commit comments

Comments
 (0)