Skip to content

Commit 53d60c2

Browse files
committed
Update DelegateMQ library
1 parent bc42c88 commit 53d60c2

Some content is hidden

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

56 files changed

+3960
-255
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ set(DMQ_ALLOCATOR "OFF") # ON for fixed-block allocator
1414
set(DMQ_LOG "OFF") # ON for spglog output
1515
set(DMQ_UTIL "ON") # ON for delegate utility classes
1616
set(DMQ_THREAD "DMQ_THREAD_STDLIB") # Set thread support library or none
17-
set(DMQ_SERIALIZE "DMQ_SERIALIZE_NONE") # Set serialization support library or none
18-
set(DMQ_TRANSPORT "DMQ_TRANSPORT_NONE") # Set transport support library or none
17+
set(DMQ_SERIALIZE "DMQ_SERIALIZE_SERIALIZE") # Set serialization support library or none
18+
set(DMQ_TRANSPORT "DMQ_TRANSPORT_WIN32_UDP") # Set transport support library or none TODO: Linux or Windows
1919
include("${CMAKE_SOURCE_DIR}/DelegateMQ/DelegateMQ.cmake")
2020

2121
# Enable integration test build

DelegateMQ/DelegateMQ.h

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,14 @@
6969
// - FreeRTOS: Uses FreeRTOSRecursiveMutex
7070
// - Bare Metal: Uses NullMutex
7171
// - StdLib: Uses std::recursive_mutex
72-
#if defined(DMQ_THREAD_STDLIB) || defined(DMQ_THREAD_FREERTOS) || defined(DMQ_THREAD_NONE)
72+
// Valid for any platform where a Mutex is defined in DelegateOpt.h
73+
#if defined(DMQ_THREAD_STDLIB) || \
74+
defined(DMQ_THREAD_FREERTOS) || \
75+
defined(DMQ_THREAD_THREADX) || \
76+
defined(DMQ_THREAD_ZEPHYR) || \
77+
defined(DMQ_THREAD_CMSIS_RTOS2) || \
78+
defined(DMQ_THREAD_QT) || \
79+
defined(DMQ_THREAD_NONE)
7380
#include "delegate/MulticastDelegateSafe.h"
7481
#include "delegate/UnicastDelegateSafe.h"
7582
#include "delegate/SignalSafe.h"
@@ -81,17 +88,24 @@
8188
// - FreeRTOS: OK
8289
// - Bare Metal: OK (Requires you to implement IThread wrapper for Event Loop)
8390
// - StdLib: OK
84-
#if defined(DMQ_THREAD_STDLIB) || defined(DMQ_THREAD_FREERTOS) || defined(DMQ_THREAD_NONE)
91+
// Valid for any platform that implements the IThread interface
92+
#if defined(DMQ_THREAD_STDLIB) || \
93+
defined(DMQ_THREAD_FREERTOS) || \
94+
defined(DMQ_THREAD_THREADX) || \
95+
defined(DMQ_THREAD_ZEPHYR) || \
96+
defined(DMQ_THREAD_CMSIS_RTOS2) || \
97+
defined(DMQ_THREAD_QT) || \
98+
defined(DMQ_THREAD_NONE)
8599
#include "delegate/DelegateAsync.h"
86100
#endif
87101

88102
// -----------------------------------------------------------------------------
89103
// 4. Asynchronous "Blocking" Delegates (Wait for Result)
90104
// -----------------------------------------------------------------------------
91-
// - FreeRTOS: NO (Requires Semaphore/Condition Variable)
92-
// - Bare Metal: NO (Cannot block/sleep)
93-
// - StdLib: OK
94-
#if defined(DMQ_THREAD_STDLIB)
105+
// Depends on std::future/std::promise.
106+
// Valid for StdLib (Windows/Linux) and Qt.
107+
// (RTOS support depends on if the toolchain provides a full C++ STL)
108+
#if defined(DMQ_THREAD_STDLIB) || defined(DMQ_THREAD_QT)
95109
#include "delegate/DelegateAsyncWait.h"
96110
#endif
97111

@@ -101,6 +115,18 @@
101115
#elif defined(DMQ_THREAD_FREERTOS)
102116
#include "predef/os/freertos/Thread.h"
103117
#include "predef/os/freertos/ThreadMsg.h"
118+
#elif defined(DMQ_THREAD_THREADX)
119+
#include "predef/os/threadx/Thread.h"
120+
#include "predef/os/threadx/ThreadMsg.h"
121+
#elif defined(DMQ_THREAD_ZEPHYR)
122+
#include "predef/os/zephyr/Thread.h"
123+
#include "predef/os/zephyr/ThreadMsg.h"
124+
#elif defined(DMQ_THREAD_CMSIS_RTOS2)
125+
#include "predef/os/cmsis-rtos2/Thread.h"
126+
#include "predef/os/cmsis-rtos2/ThreadMsg.h"
127+
#elif defined(DMQ_THREAD_QT)
128+
#include "predef/os/qt/Thread.h"
129+
#include "predef/os/qt/ThreadMsg.h"
104130
#elif defined(DMQ_THREAD_NONE)
105131
// Bare metal: User must implement their own polling/interrupt logic
106132
#else
@@ -135,12 +161,24 @@
135161
#elif defined(DMQ_TRANSPORT_WIN32_UDP)
136162
#include "predef/dispatcher/Dispatcher.h"
137163
#include "predef/transport/win32-udp/Win32UdpTransport.h"
164+
#elif defined(DMQ_TRANSPORT_WIN32_TCP)
165+
#include "predef/dispatcher/Dispatcher.h"
166+
#include "predef/transport/win32-tcp/Win32TcpTransport.h"
138167
#elif defined(DMQ_TRANSPORT_LINUX_UDP)
139168
#include "predef/dispatcher/Dispatcher.h"
140169
#include "predef/transport/linux-udp/LinuxUdpTransport.h"
170+
#elif defined(DMQ_TRANSPORT_LINUX_TCP)
171+
#include "predef/dispatcher/Dispatcher.h"
172+
#include "predef/transport/linux-tcp/LinuxTcpTransport.h"
141173
#elif defined(DMQ_TRANSPORT_MQTT)
142174
#include "predef/dispatcher/Dispatcher.h"
143175
#include "predef/transport/mqtt/MqttTransport.h"
176+
#elif defined(DMQ_TRANSPORT_SERIAL_PORT)
177+
#include "predef/dispatcher/Dispatcher.h"
178+
#include "predef/transport/serial/SerialTransport.h"
179+
#elif defined(DMQ_TRANSPORT_ARM_LWIP_UDP)
180+
#include "predef/dispatcher/Dispatcher.h"
181+
#include "predef/transport/arm-lwip-udp/ArmLwipUdpTransport.h"
144182
#elif defined(DMQ_TRANSPORT_NONE)
145183
// Create a custom application-specific transport
146184
#else

DelegateMQ/External.cmake

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,67 @@ if(DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_MQTT")
7474
set_and_check(MQTT_BINARY_DIR "/usr/local/bin")
7575
endif()
7676
endif()
77+
78+
# ---------------------------------------------------------------------------
79+
# libserialport library
80+
# ---------------------------------------------------------------------------
81+
if(DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_SERIAL_PORT")
82+
# Define the root of libserialport relative to the DelegateMQ source directory
83+
# Structure: Workspace/DelegateMQ/src/delegate-mq/External.cmake -> Workspace/libserialport
84+
set(SERIALPORT_ROOT "${DMQ_ROOT_DIR}/../../../libserialport")
85+
86+
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
87+
# 1. Header: Found in the root of the source folder (libserialport.h)
88+
set_and_check(SERIALPORT_INCLUDE_DIR "${SERIALPORT_ROOT}")
89+
90+
# 2. Library: Found in the Visual Studio build output folder
91+
# Note: Change 'Debug' to 'Release' if building in Release mode
92+
set_and_check(SERIALPORT_LIBRARY_DIR "${SERIALPORT_ROOT}/x64/Debug")
93+
94+
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
95+
# 1. Header: Found in the root of the source folder
96+
set_and_check(SERIALPORT_INCLUDE_DIR "${SERIALPORT_ROOT}")
97+
98+
# 2. Library: Found in the local build directory
99+
# Standard Autotools builds (./configure && make) place .so files in the hidden .libs/ directory
100+
if(EXISTS "${SERIALPORT_ROOT}/.libs")
101+
set_and_check(SERIALPORT_LIBRARY_DIR "${SERIALPORT_ROOT}/.libs")
102+
else()
103+
# Fallback: Check root if built differently
104+
set_and_check(SERIALPORT_LIBRARY_DIR "${SERIALPORT_ROOT}")
105+
endif()
106+
endif()
107+
endif()
108+
109+
# ---------------------------------------------------------------------------
110+
# lwIP library (For ARM/Embedded)
111+
# ---------------------------------------------------------------------------
112+
if(DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_ARM_LWIP_UDP")
113+
# Adjust this path if your lwIP root is different
114+
set(LWIP_ROOT "${DMQ_ROOT_DIR}/../../../lwip")
115+
116+
# lwIP requires 3 main include directories for the socket API
117+
set_and_check(LWIP_INCLUDE_DIR_1 "${LWIP_ROOT}/src/include")
118+
set_and_check(LWIP_INCLUDE_DIR_2 "${LWIP_ROOT}/src/include/ipv4")
119+
120+
# Often required for lwipopts.h or arch/cc.h.
121+
# NOTE: You may need to customize this depending on where your project keeps 'lwipopts.h'
122+
# For now, we point to the generic 'contrib' ports if present, or just the root.
123+
set(LWIP_INCLUDE_DIR_3 "${LWIP_ROOT}/contrib/ports/unix/port/include")
124+
125+
set(LWIP_INCLUDE_DIRS
126+
"${LWIP_INCLUDE_DIR_1}"
127+
"${LWIP_INCLUDE_DIR_2}"
128+
"${LWIP_INCLUDE_DIR_3}"
129+
)
130+
131+
# Collect core lwIP sources
132+
file(GLOB_RECURSE LWIP_SOURCES
133+
"${LWIP_ROOT}/src/core/*.c"
134+
"${LWIP_ROOT}/src/api/*.c"
135+
"${LWIP_ROOT}/src/netif/*.c"
136+
)
137+
endif()
77138

78139
# ---------------------------------------------------------------------------
79140
# MessagePack
@@ -127,6 +188,74 @@ if(DMQ_THREAD STREQUAL "DMQ_THREAD_FREERTOS")
127188
)
128189
endif()
129190

191+
# ---------------------------------------------------------------------------
192+
# ThreadX
193+
# ---------------------------------------------------------------------------
194+
if(DMQ_THREAD STREQUAL "DMQ_THREAD_THREADX")
195+
set_and_check(THREADX_ROOT_DIR "${DMQ_ROOT_DIR}/../../../threadx")
196+
197+
# Collect Common Core Sources
198+
file(GLOB THREADX_SOURCES
199+
"${THREADX_ROOT_DIR}/common/src/*.c"
200+
"${THREADX_ROOT_DIR}/common/inc/*.h"
201+
)
202+
203+
# Note: You generally need to append architecture-specific port sources here
204+
# Example for Windows Simulation (MSVC):
205+
if(MSVC)
206+
# file(GLOB PORT_SOURCES "${THREADX_ROOT_DIR}/ports/win32/vs_2019/src/*.c")
207+
# list(APPEND THREADX_SOURCES ${PORT_SOURCES})
208+
endif()
209+
endif()
210+
211+
# ---------------------------------------------------------------------------
212+
# Zephyr
213+
# ---------------------------------------------------------------------------
214+
if(DMQ_THREAD STREQUAL "DMQ_THREAD_ZEPHYR")
215+
# Zephyr is a build system, not just a library.
216+
# We typically do NOT manually glob source files here.
217+
# The application's main CMakeLists.txt must call `find_package(Zephyr)`
218+
# which sets up the include paths and kernel linking automatically.
219+
220+
# Optional: Just verify the root directory exists if you want to be safe
221+
set_and_check(ZEPHYR_ROOT_DIR "${DMQ_ROOT_DIR}/../../../zephyr")
222+
223+
# Do NOT glob sources. Zephyr builds itself.
224+
endif()
225+
226+
# ---------------------------------------------------------------------------
227+
# CMSIS-RTOS2
228+
# ---------------------------------------------------------------------------
229+
if(DMQ_THREAD STREQUAL "DMQ_THREAD_CMSIS_RTOS2")
230+
# CMSIS is usually provided by the IDE (Keil/IAR) or a silicon vendor pack (STM32Cube).
231+
# We do NOT glob sources here by default.
232+
# Users must ensure the 'cmsis_os2.h' path is in their include path.
233+
endif()
234+
235+
# ---------------------------------------------------------------------------
236+
# Qt Framework
237+
# ---------------------------------------------------------------------------
238+
if(DMQ_THREAD STREQUAL "DMQ_THREAD_QT")
239+
add_compile_definitions(DMQ_THREAD_QT)
240+
241+
# Find the Qt packages (Core is usually sufficient for QThread)
242+
find_package(Qt6 COMPONENTS Core REQUIRED)
243+
# Or Qt5: find_package(Qt5 COMPONENTS Core REQUIRED)
244+
245+
# Collect the source files
246+
file(GLOB THREAD_SOURCES
247+
"${DMQ_ROOT_DIR}/predef/os/qt/*.cpp"
248+
"${DMQ_ROOT_DIR}/predef/os/qt/*.h"
249+
)
250+
251+
# Important: Enable CMAKE_AUTOMOC for the Qt Meta-Object system
252+
# (needed for signals/slots in Thread.h)
253+
set(CMAKE_AUTOMOC ON)
254+
255+
# You might need to link Qt6::Core to your main target later:
256+
# target_link_libraries(YourApp PRIVATE Qt6::Core)
257+
endif()
258+
130259
# ---------------------------------------------------------------------------
131260
# spdlog
132261
# ---------------------------------------------------------------------------

DelegateMQ/Predef.cmake

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,24 @@ elseif (DMQ_THREAD STREQUAL "DMQ_THREAD_FREERTOS")
1212
"${DMQ_ROOT_DIR}/predef/os/freertos/*.c*"
1313
"${DMQ_ROOT_DIR}/predef/os/freertos/*.h"
1414
)
15+
elseif (DMQ_THREAD STREQUAL "DMQ_THREAD_THREADX")
16+
add_compile_definitions(DMQ_THREAD_THREADX)
17+
file(GLOB THREAD_SOURCES
18+
"${DMQ_ROOT_DIR}/predef/os/threadx/*.c*"
19+
"${DMQ_ROOT_DIR}/predef/os/threadx/*.h"
20+
)
21+
elseif (DMQ_THREAD STREQUAL "DMQ_THREAD_ZEPHYR")
22+
add_compile_definitions(DMQ_THREAD_ZEPHYR)
23+
file(GLOB THREAD_SOURCES
24+
"${DMQ_ROOT_DIR}/predef/os/zephyr/*.c*"
25+
"${DMQ_ROOT_DIR}/predef/os/zephyr/*.h"
26+
)
27+
elseif (DMQ_THREAD STREQUAL "DMQ_THREAD_CMSIS_RTOS2")
28+
add_compile_definitions(DMQ_THREAD_CMSIS_RTOS2)
29+
file(GLOB THREAD_SOURCES
30+
"${DMQ_ROOT_DIR}/predef/os/cmsis-rtos2/*.c*"
31+
"${DMQ_ROOT_DIR}/predef/os/cmsis-rtos2/*.h"
32+
)
1533
elseif (DMQ_THREAD STREQUAL "DMQ_THREAD_NONE")
1634
add_compile_definitions(DMQ_THREAD_NONE)
1735
else()
@@ -56,9 +74,21 @@ elseif (DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_WIN32_PIPE")
5674
elseif (DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_WIN32_UDP")
5775
add_compile_definitions(DMQ_TRANSPORT_WIN32_UDP)
5876
file(GLOB TRANSPORT_SOURCES "${DMQ_ROOT_DIR}/predef/transport/win32-udp/*.h")
77+
elseif (DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_WIN32_TCP")
78+
add_compile_definitions(DMQ_TRANSPORT_WIN32_TCP)
79+
file(GLOB TRANSPORT_SOURCES "${DMQ_ROOT_DIR}/predef/transport/win32-tcp/*.h")
5980
elseif (DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_LINUX_UDP")
6081
add_compile_definitions(DMQ_TRANSPORT_LINUX_UDP)
6182
file(GLOB TRANSPORT_SOURCES "${DMQ_ROOT_DIR}/predef/transport/linux-udp/*.h")
83+
elseif (DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_LINUX_TCP")
84+
add_compile_definitions(DMQ_TRANSPORT_LINUX_TCP)
85+
file(GLOB TRANSPORT_SOURCES "${DMQ_ROOT_DIR}/predef/transport/linux-tcp/*.h")
86+
elseif (DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_SERIAL_PORT")
87+
add_compile_definitions(DMQ_TRANSPORT_SERIAL_PORT)
88+
file(GLOB TRANSPORT_SOURCES "${DMQ_ROOT_DIR}/predef/transport/serial/*.h")
89+
elseif (DMQ_TRANSPORT STREQUAL "DMQ_TRANSPORT_ARM_LWIP_UDP")
90+
add_compile_definitions(DMQ_TRANSPORT_ARM_LWIP_UDP)
91+
file(GLOB TRANSPORT_SOURCES "${DMQ_ROOT_DIR}/predef/transport/arm-lwip-udp/*.h")
6292
else()
6393
message(FATAL_ERROR "Must set DMQ_TRANSPORT option.")
6494
endif()

DelegateMQ/delegate/DelegateOpt.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
#if defined(DMQ_THREAD_FREERTOS)
1111
#include "predef/util/FreeRTOSClock.h"
1212
#include "predef/util/FreeRTOSMutex.h"
13+
#elif defined(DMQ_THREAD_THREADX)
14+
#include "predef/util/ThreadXClock.h"
15+
#include "predef/util/ThreadXMutex.h"
16+
#elif defined(DMQ_THREAD_CMSIS_RTOS2)
17+
#include "predef/util/CmsisRtos2Clock.h"
18+
#include "predef/util/CmsisRtos2Mutex.h"
1319
#elif defined(DMQ_THREAD_NONE)
1420
#include "predef/util/BareMetalClock.h"
1521
#endif
@@ -23,12 +29,23 @@ namespace dmq
2329
// Use the custom FreeRTOS wrapper
2430
using Clock = dmq::FreeRTOSClock;
2531

32+
#elif defined(DMQ_THREAD_THREADX)
33+
// Use the custom ThreadX wrapper
34+
using Clock = dmq::ThreadXClock;
35+
36+
#elif defined(DMQ_THREAD_ZEPHYR)
37+
// Use the custom Zephyr wrapper
38+
using Clock = dmq::ZephyrClock;
39+
2640
#elif defined(DMQ_THREAD_NONE)
2741
// Assuming implemented the 'g_ticks' variable
2842
using Clock = dmq::BareMetalClock;
2943

44+
#elif defined(DMQ_THREAD_CMSIS_RTOS2)
45+
using Clock = dmq::CmsisRtos2Clock;
46+
3047
#else
31-
// Windows / Linux / macOS (Standard)
48+
// Windows / Linux / macOS / Qt
3249
using Clock = std::chrono::steady_clock;
3350
#endif
3451

@@ -43,6 +60,20 @@ namespace dmq
4360
using Mutex = dmq::FreeRTOSMutex;
4461
using RecursiveMutex = dmq::FreeRTOSRecursiveMutex;
4562

63+
#elif defined(DMQ_THREAD_THREADX)
64+
// Use the custom ThreadX wrapper
65+
using Mutex = dmq::ThreadXMutex;
66+
using RecursiveMutex = dmq::ThreadXRecursiveMutex;
67+
68+
#elif defined(DMQ_THREAD_ZEPHYR)
69+
// Use the custom Zephyr wrapper
70+
using Mutex = dmq::ZephyrMutex;
71+
using RecursiveMutex = dmq::ZephyrRecursiveMutex;
72+
73+
#elif defined(DMQ_THREAD_CMSIS_RTOS2)
74+
using Mutex = dmq::CmsisRtos2Mutex;
75+
using RecursiveMutex = dmq::CmsisRtos2RecursiveMutex;
76+
4677
#elif defined(DMQ_THREAD_NONE)
4778
// Bare metal has no threads, so no locking is required.
4879
// We define a dummy "No-Op" mutex.
@@ -54,7 +85,7 @@ namespace dmq
5485
using RecursiveMutex = NullMutex;
5586

5687
#else
57-
// Windows / Linux / macOS
88+
// Windows / Linux / macOS / Qt
5889
using Mutex = std::mutex;
5990
using RecursiveMutex = std::recursive_mutex;
6091
#endif

DelegateMQ/predef/dispatcher/Dispatcher.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
#ifndef DISPATCHER_H
22
#define DISPATCHER_H
33

4-
/// @file
4+
/// @file Dispatcher.h
55
/// @see https://github.com/endurodave/DelegateMQ
66
/// David Lafreniere, 2025.
77
///
8-
/// Dispatch callable argument data to a remote endpoint.
8+
/// @brief The bridge between the serialization layer and the physical transport layer.
9+
///
10+
/// @details
11+
/// The `Dispatcher` class is responsible for packaging serialized function arguments
12+
/// into a valid DelegateMQ message and handing it off to the transport.
13+
///
14+
/// **Key Responsibilities:**
15+
/// 1. **Message Construction:** Creates the protocol header (`DmqHeader`) containing
16+
/// the Remote ID and a monotonic Sequence Number.
17+
/// 2. **Stream Management:** Validates that the output stream is compatible
18+
/// (expects `xostringstream`).
19+
/// 3. **Dispatch:** Forwards the header and the serialized payload (stream) to the
20+
/// registered `ITransport::Send()` method.
21+
///
22+
/// **Usage:**
23+
/// This class is typically used internally by `DelegateRemote` to finalize a remote
24+
/// procedure call before transmission.
925

1026
#include "delegate/IDispatcher.h"
1127
#include "predef/transport/DmqHeader.h"

0 commit comments

Comments
 (0)