Skip to content

Commit a5d4aaa

Browse files
committed
Update DelegateMQ library
1 parent 3fbd01f commit a5d4aaa

File tree

19 files changed

+423
-138
lines changed

19 files changed

+423
-138
lines changed

DelegateMQ/Defaults.cmake

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# DelegateMQ Defaults
2+
#
3+
# This module auto-selects default DelegateMQ build options based on the target platform.
4+
# Options can be overridden by setting the variables before including DelegateMQ.cmake.
5+
6+
# --- Threading Defaults ---
7+
if(NOT DEFINED DMQ_THREAD)
8+
if(WIN32 OR UNIX)
9+
set(DMQ_THREAD "DMQ_THREAD_STDLIB")
10+
elseif(FREERTOS OR FREE_RTOS)
11+
set(DMQ_THREAD "DMQ_THREAD_FREERTOS")
12+
elseif(THREADX)
13+
set(DMQ_THREAD "DMQ_THREAD_THREADX")
14+
elseif(ZEPHYR)
15+
set(DMQ_THREAD "DMQ_THREAD_ZEPHYR")
16+
elseif(CMSIS_RTOS2)
17+
set(DMQ_THREAD "DMQ_THREAD_CMSIS_RTOS2")
18+
else()
19+
set(DMQ_THREAD "DMQ_THREAD_NONE")
20+
endif()
21+
endif()
22+
23+
# --- Transport Defaults ---
24+
if(NOT DEFINED DMQ_TRANSPORT)
25+
if(WIN32)
26+
set(DMQ_TRANSPORT "DMQ_TRANSPORT_WIN32_UDP")
27+
elseif(UNIX AND NOT APPLE)
28+
set(DMQ_TRANSPORT "DMQ_TRANSPORT_LINUX_UDP")
29+
else()
30+
set(DMQ_TRANSPORT "DMQ_TRANSPORT_NONE")
31+
endif()
32+
endif()
33+
34+
# --- Serialization Defaults ---
35+
if(NOT DEFINED DMQ_SERIALIZE)
36+
if(WIN32 OR UNIX)
37+
set(DMQ_SERIALIZE "DMQ_SERIALIZE_SERIALIZE")
38+
else()
39+
set(DMQ_SERIALIZE "DMQ_SERIALIZE_NONE")
40+
endif()
41+
endif()
42+
43+
# --- Utility Class Defaults ---
44+
if(NOT DEFINED DMQ_UTIL)
45+
set(DMQ_UTIL "ON")
46+
endif()
47+
48+
# --- DataBus Defaults ---
49+
if(NOT DEFINED DMQ_DATABUS)
50+
if(WIN32 OR UNIX)
51+
set(DMQ_DATABUS "ON")
52+
else()
53+
set(DMQ_DATABUS "OFF")
54+
endif()
55+
endif()
56+
57+
# --- DataBus Tools Defaults ---
58+
if(NOT DEFINED DMQ_DATABUS_TOOLS)
59+
if(DMQ_DATABUS STREQUAL "ON" AND (WIN32 OR UNIX))
60+
set(DMQ_DATABUS_TOOLS "ON")
61+
else()
62+
set(DMQ_DATABUS_TOOLS "OFF")
63+
endif()
64+
endif()
65+
66+
# --- Allocator Defaults ---
67+
if(NOT DEFINED DMQ_ALLOCATOR)
68+
set(DMQ_ALLOCATOR "OFF")
69+
endif()
70+
71+
# --- Assert Defaults ---
72+
if(NOT DEFINED DMQ_ASSERTS)
73+
set(DMQ_ASSERTS "OFF")
74+
endif()
75+
76+
# --- Logging Defaults ---
77+
if(NOT DEFINED DMQ_LOG)
78+
set(DMQ_LOG "OFF")
79+
endif()

DelegateMQ/DelegateMQ.cmake

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,9 @@
99
#
1010
# Set DMQ build options:
1111
#
12-
# # Set DMQ build options. Update as necessary.
13-
# set(DMQ_ASSERTS "OFF")
14-
# set(DMQ_ALLOCATOR "OFF")
15-
# set(DMQ_LOG "OFF")
16-
# set(DMQ_UTIL "ON")
12+
# # Optional: Set DMQ build options to override defaults.
1713
# set(DMQ_THREAD "DMQ_THREAD_STDLIB")
18-
# set(DMQ_SERIALIZE "DMQ_SERIALIZE_NONE")
19-
# set(DMQ_TRANSPORT "DMQ_TRANSPORT_NONE")
20-
# include("${CMAKE_SOURCE_DIR}/../../../src/delegate-mq/DelegateMQ.cmake")
14+
# include("${CMAKE_SOURCE_DIR}/src/delegate-mq/DelegateMQ.cmake")
2115
#
2216
# Use variables to build:
2317
#
@@ -41,6 +35,9 @@ endmacro()
4135
set_and_check(DMQ_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}")
4236
set_and_check(DMQ_INCLUDE_DIR "${DMQ_ROOT_DIR}")
4337

38+
check("${DMQ_ROOT_DIR}/Defaults.cmake")
39+
include ("${DMQ_ROOT_DIR}/Defaults.cmake")
40+
4441
check("${DMQ_ROOT_DIR}/Macros.cmake")
4542
include ("${DMQ_ROOT_DIR}/Macros.cmake")
4643

DelegateMQ/External.cmake

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,18 +193,16 @@ endif()
193193
# FreeRTOS
194194
# ---------------------------------------------------------------------------
195195
if(DMQ_THREAD STREQUAL "DMQ_THREAD_FREERTOS")
196-
set_and_check(FREERTOS_ROOT_DIR "${DMQ_ROOT_DIR}/../../../FreeRTOSv202212.00")
196+
set_and_check(FREERTOS_ROOT_DIR "${DMQ_ROOT_DIR}/../../../FreeRTOS")
197197

198198
file(GLOB FREERTOS_SOURCES
199-
"${FREERTOS_ROOT_DIR}/FreeRTOS/Source/*.c"
200-
"${FREERTOS_ROOT_DIR}/FreeRTOS/Source/include/*.h"
199+
"${FREERTOS_ROOT_DIR}/*.c"
200+
"${FREERTOS_ROOT_DIR}/include/*.h"
201201
)
202202

203-
list(APPEND FREERTOS_SOURCES
204-
"${FREERTOS_ROOT_DIR}/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c"
205-
"${FREERTOS_ROOT_DIR}/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c"
206-
"${FREERTOS_ROOT_DIR}/FreeRTOS/Source/portable/MSVC-MingW/port.c"
207-
"${FREERTOS_ROOT_DIR}/FreeRTOS/Source/portable/MemMang/heap_5.c"
203+
list(APPEND FREERTOS_SOURCES
204+
"${FREERTOS_ROOT_DIR}/portable/MSVC-MingW/port.c"
205+
"${FREERTOS_ROOT_DIR}/portable/MemMang/heap_5.c"
208206
)
209207
endif()
210208

DelegateMQ/delegate/DelegateOpt.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,60 @@
44
/// @file
55
/// @brief Delegate library options header file.
66

7+
#if defined(_WIN32) || defined(_WIN64)
8+
#ifndef WIN32_LEAN_AND_MEAN
9+
#define WIN32_LEAN_AND_MEAN
10+
#endif
11+
12+
// If networking is active, include winsock2.h here to prevent macro
13+
// redefinitions when windows.h is included later (e.g. by FreeRTOS or stdlib).
14+
#if defined(DMQ_DATABUS) || defined(DMQ_TRANSPORT_ZEROMQ) || \
15+
defined(DMQ_TRANSPORT_WIN32_UDP) || defined(DMQ_TRANSPORT_WIN32_TCP) || \
16+
defined(DMQ_TRANSPORT_WIN32_PIPE) || defined(DMQ_TRANSPORT_NNG) || \
17+
defined(DMQ_TRANSPORT_MQTT)
18+
#include <winsock2.h>
19+
#include <ws2tcpip.h>
20+
#endif
21+
#endif
22+
23+
// --- PLATFORM AUTO-DETECTION ---
24+
// If no threading model is defined, attempt to auto-select a default
25+
#if !defined(DMQ_THREAD_STDLIB) && !defined(DMQ_THREAD_WIN32) && \
26+
!defined(DMQ_THREAD_FREERTOS) && !defined(DMQ_THREAD_THREADX) && \
27+
!defined(DMQ_THREAD_ZEPHYR) && !defined(DMQ_THREAD_CMSIS_RTOS2) && \
28+
!defined(DMQ_THREAD_QT) && !defined(DMQ_THREAD_NONE)
29+
30+
#if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__unix__)
31+
#define DMQ_THREAD_STDLIB
32+
#endif
33+
#endif
34+
35+
// If no serialization model is defined, attempt to auto-select a default
36+
#if !defined(DMQ_SERIALIZE_SERIALIZE) && !defined(DMQ_SERIALIZE_RAPIDJSON) && \
37+
!defined(DMQ_SERIALIZE_MSGPACK) && !defined(DMQ_SERIALIZE_CEREAL) && \
38+
!defined(DMQ_SERIALIZE_BITSERY) && !defined(DMQ_SERIALIZE_NONE)
39+
40+
#if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__unix__)
41+
#define DMQ_SERIALIZE_SERIALIZE
42+
#else
43+
#define DMQ_SERIALIZE_NONE
44+
#endif
45+
#endif
46+
47+
// Default to DataBus ON on Desktop if not explicitly disabled
48+
#if !defined(DMQ_DATABUS) && !defined(DMQ_DATABUS_OFF)
49+
#if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__unix__)
50+
#define DMQ_DATABUS
51+
#endif
52+
#endif
53+
54+
// Default to DataBus Tools ON on Desktop if DataBus is active and not explicitly disabled
55+
#if defined(DMQ_DATABUS) && !defined(DMQ_DATABUS_TOOLS) && !defined(DMQ_DATABUS_TOOLS_OFF)
56+
#if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__unix__)
57+
#define DMQ_DATABUS_TOOLS
58+
#endif
59+
#endif
60+
761
#include <chrono>
862
#if defined(DMQ_THREAD_STDLIB) || defined(DMQ_THREAD_WIN32) || defined(DMQ_THREAD_QT)
963
#include <mutex>
@@ -33,6 +87,8 @@
3387
#elif defined(DMQ_THREAD_CMSIS_RTOS2)
3488
#include "predef/util/CmsisRtos2Clock.h"
3589
#include "predef/util/CmsisRtos2Mutex.h"
90+
#elif defined(DMQ_THREAD_NONE)
91+
#include "predef/util/BareMetalClock.h"
3692
#else
3793
#include "predef/util/BareMetalClock.h"
3894
#endif

DelegateMQ/predef/os/cmsis-rtos2/Thread.cpp

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ using namespace dmq;
1515
//----------------------------------------------------------------------------
1616
Thread::Thread(const std::string& threadName, size_t maxQueueSize)
1717
: THREAD_NAME(threadName)
18+
, m_exit(false)
1819
{
1920
// If 0 is passed, use the default size
2021
m_queueSize = (maxQueueSize == 0) ? DEFAULT_QUEUE_SIZE : maxQueueSize;
@@ -93,12 +94,14 @@ void Thread::ExitThread()
9394
{
9495
if (m_msgq != NULL)
9596
{
97+
m_exit.store(true);
98+
9699
// Send exit message
97100
ThreadMsg* msg = new (std::nothrow) ThreadMsg(MSG_EXIT_THREAD);
98101
if (msg)
99102
{
100-
// Send pointer, wait 100 ticks max
101-
if (osMessageQueuePut(m_msgq, &msg, 0, 100) != osOK)
103+
// Send pointer, wait forever to ensure it gets in.
104+
if (osMessageQueuePut(m_msgq, &msg, 0, osWaitForever) != osOK)
102105
{
103106
delete msg; // Failed to send
104107
}
@@ -112,12 +115,7 @@ void Thread::ExitThread()
112115
}
113116

114117
// Thread has finished Run(). Now we can safely clean up resources.
115-
116-
// Terminate ensures the thread is in INACTIVE state and resources are reclaimed.
117-
if (m_thread) {
118-
osThreadTerminate(m_thread);
119-
m_thread = NULL;
120-
}
118+
m_thread = NULL;
121119

122120
if (m_msgq) {
123121
osMessageQueueDelete(m_msgq);
@@ -150,6 +148,17 @@ bool Thread::IsCurrentThread()
150148
return GetThreadId() == GetCurrentThreadId();
151149
}
152150

151+
//----------------------------------------------------------------------------
152+
// GetQueueSize
153+
//----------------------------------------------------------------------------
154+
size_t Thread::GetQueueSize()
155+
{
156+
if (m_msgq != NULL) {
157+
return (size_t)osMessageQueueGetCount(m_msgq);
158+
}
159+
return 0;
160+
}
161+
153162
//----------------------------------------------------------------------------
154163
// DispatchDelegate
155164
//----------------------------------------------------------------------------
@@ -192,17 +201,16 @@ void Thread::Run()
192201
{
193202
ThreadMsg* msg = nullptr;
194203

195-
while (true)
204+
while (!m_exit.load())
196205
{
197206
// Block forever waiting for a message
198207
// msg is a pointer to ThreadMsg*. The queue holds the pointer.
199208
if (osMessageQueueGet(m_msgq, &msg, NULL, osWaitForever) == osOK)
200209
{
201210
if (!msg) continue;
202211

203-
switch (msg->GetId())
204-
{
205-
case MSG_DISPATCH_DELEGATE:
212+
int msgId = msg->GetId();
213+
if (msgId == MSG_DISPATCH_DELEGATE)
206214
{
207215
auto delegateMsg = msg->GetData();
208216
if (delegateMsg) {
@@ -211,24 +219,18 @@ void Thread::Run()
211219
invoker->Invoke(delegateMsg);
212220
}
213221
}
214-
break;
215-
}
216-
217-
case MSG_EXIT_THREAD:
218-
{
219-
delete msg;
220-
// Signal ExitThread() that we are done
221-
if (m_exitSem) {
222-
osSemaphoreRelease(m_exitSem);
223-
}
224-
return;
225222
}
223+
224+
delete msg;
226225

227-
default:
226+
if (msgId == MSG_EXIT_THREAD) {
228227
break;
229228
}
230-
231-
delete msg;
232229
}
233230
}
231+
232+
// Signal ExitThread() that we are done
233+
if (m_exitSem) {
234+
osSemaphoreRelease(m_exitSem);
235+
}
234236
}

DelegateMQ/predef/os/cmsis-rtos2/Thread.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@
1313
/// asynchronous delegates to a dedicated thread on any CMSIS-compliant RTOS
1414
/// (e.g., Keil RTX, FreeRTOS wrapped by CMSIS, Zephyr, etc.).
1515
///
16+
/// @note This implementation is a basic port. For reference, the stdlib and win32
17+
/// implementations provide additional features:
18+
/// 1. Priority Support: Uses a priority queue to respect dmq::Priority.
19+
/// 2. Back Pressure: DispatchDelegate() blocks if the queue is full.
20+
/// 3. Watchdog: Includes a ThreadCheck() heartbeat mechanism.
21+
/// 4. Synchronized Startup: CreateThread() blocks until the worker thread is ready.
22+
///
1623
/// **Key Features:**
1724
/// * **Task Integration:** Wraps `osThreadNew` to establish a dedicated worker loop.
1825
/// * **Queue-Based Dispatch:** Uses `osMessageQueue` to receive and process incoming
@@ -26,6 +33,7 @@
2633
#include "cmsis_os2.h"
2734
#include <string>
2835
#include <memory>
36+
#include <atomic>
2937

3038
class ThreadMsg;
3139

@@ -60,6 +68,9 @@ class Thread : public dmq::IThread
6068

6169
std::string GetThreadName() { return THREAD_NAME; }
6270

71+
/// Get current queue size
72+
size_t GetQueueSize();
73+
6374
virtual void DispatchDelegate(std::shared_ptr<dmq::DelegateMsg> msg) override;
6475

6576
private:
@@ -70,17 +81,17 @@ class Thread : public dmq::IThread
7081
static void Process(void* argument);
7182
void Run();
7283

84+
const std::string THREAD_NAME;
85+
size_t m_queueSize;
86+
osPriority_t m_priority;
87+
7388
osThreadId_t m_thread = NULL;
7489
osMessageQueueId_t m_msgq = NULL;
7590
osSemaphoreId_t m_exitSem = NULL; // Semaphore to signal thread completion
76-
77-
const std::string THREAD_NAME;
91+
std::atomic<bool> m_exit = false;
7892

7993
// Configurable sizes
8094
static const uint32_t STACK_SIZE = 2048; // Bytes
81-
82-
size_t m_queueSize;
83-
osPriority_t m_priority;
8495
};
8596

8697
#endif // _THREAD_CMSIS_RTOS2_H

0 commit comments

Comments
 (0)