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
+6-3Lines changed: 6 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ DelegateMQ is a C++ header-only library for invoking any callable (e.g., functio
14
14
- Asynchronously
15
15
- Remotely across processes or processors
16
16
17
-
It unifies function calls across threads or systems via a simple delegate interface. DelegateMQ is thread-safe, unit-tested, and easy to port to any platform.
17
+
It unifies function calls across threads or systems via a simple delegate interface. A powerful, lightweight messaging library for thread-safe asynchronous callbacks, non-blocking APIs, and passing data between threads. DelegateMQ is thread-safe, unit-tested, and easy to port to any platform.
@@ -244,7 +246,7 @@ Numerous predefined platforms are already supported such as Windows, Linux, and
244
246
3.**Implement `ISerializer` and `ITransport`**: Required to use **Remote** delegates across processes/processors.
245
247
**Optional:* Implement `ITransportMonitor` if your application layer requires command acknowledgments (ACKs).
246
248
* See [Sample Projects](#sample-projects) for numerous remote delegate examples.
247
-
4.**Check System Clock**: Ensure `std::chrono::steady_clock` is supported on your target hardware, as it is required for timers and transport timeouts.
249
+
4.**Check System Clock**: Ensure `std::chrono::steady_clock` is supported on your target hardware, as it is required for timers and transport timeouts. Otherwise, change `dmw::Clock` in `DelegateOpt.h` to a new clock type.
248
250
5.**Call `Timer::ProcessTimers()`**: Periodically call `ProcessTimers()` (e.g., from a main loop or hardware timer ISR) to support timers and thread watchdogs.
249
251
6.**Configure Build Options**: Set CMake DMQ library build options within `CMakeLists.txt`.
250
252
* Example: `DMQ_ASSERTS` for debug assertions.
@@ -954,9 +956,9 @@ safeObj.reset();
954
956
955
957
When using `std::shared_ptr` and `std::enable_shared_from_this`, you must follow a specific pattern to manually register and unregister delegates.
956
958
957
-
Critical Rule: You cannot call `shared_from_this()` inside a destructor. Doing so causes a std::bad_weak_ptr crash because the ownership of the object has already expired. Therefore, if you require manual unregistration (to stop receiving events immediately), you must use an explicit Init/Term pattern.
959
+
Critical Rule: You cannot call `shared_from_this()` inside a destructor. Doing so causes a `std::bad_weak_ptr` crash because the ownership of the object has already expired. Therefore, if you require manual unregistration (to stop receiving events immediately), you must use an explicit Init/Term or RAII pattern.
958
960
959
-
### The Init/Term Pattern
961
+
### Init/Term Pattern
960
962
961
963
`Init()`: Called after the object is fully constructed and owned by a `shared_ptr`. Registers the delegate.
962
964
@@ -1014,6 +1016,65 @@ void RunClient()
1014
1016
}
1015
1017
```
1016
1018
1019
+
### RAII Pattern
1020
+
1021
+
Alternative solution does not require calling `Term()`.
This table outlines when it is safe to use raw pointers (`this`) during delegate registration versus when you must use `std::shared_ptr` (`shared_from_this()`) to prevent crashes.
1069
+
1070
+
| Delegate Type | Behavior | Safe to use `this`? | Explanation |
1071
+
| --- | --- | --- | --- |
1072
+
| Synchronous | Function is called immediately on the current thread.| YES | The caller waits for the callback to complete. It is impossible for the object to be destroyed while the callback is running. Must unregister in destructor. |
1073
+
| Async (Non-Blocking) | "Fire and Forget." Message posted to target thread queue. Caller continues immediately. | NO | Unsafe. Even if you unregister in the destructor, a message may already be pending in the queue. If the object dies before the queue is processed, the target thread will access freed memory. Use `shared_from_this()`. |
1074
+
| Async Blocking (`WAIT_INFINITE`) | Caller thread blocks until the target thread executes the function. | YES | Because the caller is blocked, the object (owned by the caller) cannot go out of scope or be destroyed until the callback finishes. |
1075
+
| Async Blocking (Timeout) | Caller thread blocks until success OR timeout expires. | NO | Unsafe. If the timeout expires, the caller proceeds and may destroy the object. However, the message is still in the queue. When the target thread eventually processes it, it will crash. Use `shared_from_this()`. |
1076
+
| Async (Singleton / Global) | Object lifetime exceeds the thread lifetime (e.g., Singleton, Static, or Global). | YES | Safe. Since the object is guaranteed to exist for the entire duration of the application (or until after the worker thread is destroyed), the pointer will never be invalid. |
1077
+
1017
1078
## Library Dependencies
1018
1079
1019
1080
The `DelegateMQ` library external dependencies are based upon on the intended use. Interfaces provide the delegate library with platform-specific features to ease porting to a target system. Complete example code offer ready-made solutions or create your own.
0 commit comments