Skip to content

Commit 397e6d9

Browse files
committed
Update DelegateMQ library
1 parent b71ab83 commit 397e6d9

File tree

9 files changed

+94
-55
lines changed

9 files changed

+94
-55
lines changed

DelegateMQ/delegate/DelegateAsyncWait.h

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#ifndef _DELEGATE_ASYNC_WAIT_H
22
#define _DELEGATE_ASYNC_WAIT_H
33

4+
#include "DelegateOpt.h"
5+
#ifdef DMQ_HAS_CV
6+
47
// DelegateAsyncWait.h
58
// @see https://github.com/DelegateMQ/DelegateMQ
69
// David Lafreniere, Aug 2020.
@@ -344,14 +347,14 @@ class DelegateFreeAsyncWait<RetType(Args...)> : public DelegateFree<RetType(Args
344347
// Wait for destination thread to execute the delegate function and get return value
345348
if (msg->GetSema().Wait(m_timeout)) {
346349
// Wait succeeded. Now acquire lock to safely read the value.
347-
const std::lock_guard<Mutex> lock(msg->GetLock());
350+
const dmq::LockGuard<Mutex> lock(msg->GetLock());
348351
m_success = true;
349352
m_retVal = delegate->m_retVal;
350353
}
351354
}
352355

353356
// Protect data shared between source and destination threads
354-
const std::lock_guard<Mutex> lock(msg->GetLock());
357+
const dmq::LockGuard<Mutex> lock(msg->GetLock());
355358

356359
// Set flag that source is not waiting anymore
357360
msg->SetInvokerWaiting(false);
@@ -406,7 +409,7 @@ class DelegateFreeAsyncWait<RetType(Args...)> : public DelegateFree<RetType(Args
406409
return false;
407410

408411
// Protect data shared between source and destination threads
409-
const std::lock_guard<Mutex> lock(delegateMsg->GetLock());
412+
const dmq::LockGuard<Mutex> lock(delegateMsg->GetLock());
410413

411414
// Is the source thread waiting for the target function invoke to complete?
412415
if (delegateMsg->GetInvokerWaiting()) {
@@ -780,14 +783,14 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
780783
// Wait for destination thread to execute the delegate function and get return value
781784
if (msg->GetSema().Wait(m_timeout)) {
782785
// Wait succeeded. Now acquire lock to safely read the value.
783-
const std::lock_guard<Mutex> lock(msg->GetLock());
786+
const dmq::LockGuard<Mutex> lock(msg->GetLock());
784787
m_success = true;
785788
m_retVal = delegate->m_retVal;
786789
}
787790
}
788791

789792
// Protect data shared between source and destination threads
790-
const std::lock_guard<Mutex> lock(msg->GetLock());
793+
const dmq::LockGuard<Mutex> lock(msg->GetLock());
791794

792795
// Set flag that source is not waiting anymore
793796
msg->SetInvokerWaiting(false);
@@ -842,7 +845,7 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
842845
return false;
843846

844847
// Protect data shared between source and destination threads
845-
const std::lock_guard<Mutex> lock(delegateMsg->GetLock());
848+
const dmq::LockGuard<Mutex> lock(delegateMsg->GetLock());
846849

847850
// Is the source thread waiting for the target function invoke to complete?
848851
if (delegateMsg->GetInvokerWaiting()) {
@@ -1133,14 +1136,14 @@ class DelegateMemberAsyncWaitSp<TClass, RetType(Args...)> : public DelegateMembe
11331136
// Wait for destination thread to execute the delegate function and get return value
11341137
if (msg->GetSema().Wait(m_timeout)) {
11351138
// Wait succeeded. Now acquire lock to safely read the value.
1136-
const std::lock_guard<Mutex> lock(msg->GetLock());
1139+
const dmq::LockGuard<Mutex> lock(msg->GetLock());
11371140
m_success = true;
11381141
m_retVal = delegate->m_retVal;
11391142
}
11401143
}
11411144

11421145
// Protect data shared between source and destination threads
1143-
const std::lock_guard<Mutex> lock(msg->GetLock());
1146+
const dmq::LockGuard<Mutex> lock(msg->GetLock());
11441147

11451148
// Set flag that source is not waiting anymore
11461149
msg->SetInvokerWaiting(false);
@@ -1195,7 +1198,7 @@ class DelegateMemberAsyncWaitSp<TClass, RetType(Args...)> : public DelegateMembe
11951198
return false;
11961199

11971200
// Protect data shared between source and destination threads
1198-
const std::lock_guard<Mutex> lock(delegateMsg->GetLock());
1201+
const dmq::LockGuard<Mutex> lock(delegateMsg->GetLock());
11991202

12001203
// Is the source thread waiting for the target function invoke to complete?
12011204
if (delegateMsg->GetInvokerWaiting()) {
@@ -1488,14 +1491,14 @@ class DelegateFunctionAsyncWait<RetType(Args...)> : public DelegateFunction<RetT
14881491
// Wait for destination thread to execute the delegate function and get return value
14891492
if (msg->GetSema().Wait(m_timeout)) {
14901493
// Wait succeeded. Now acquire lock to safely read the value.
1491-
const std::lock_guard<Mutex> lock(msg->GetLock());
1494+
const dmq::LockGuard<Mutex> lock(msg->GetLock());
14921495
m_success = true;
14931496
m_retVal = delegate->m_retVal;
14941497
}
14951498
}
14961499

14971500
// Protect data shared between source and destination threads
1498-
const std::lock_guard<Mutex> lock(msg->GetLock());
1501+
const dmq::LockGuard<Mutex> lock(msg->GetLock());
14991502

15001503
// Set flag that source is not waiting anymore
15011504
msg->SetInvokerWaiting(false);
@@ -1550,7 +1553,7 @@ class DelegateFunctionAsyncWait<RetType(Args...)> : public DelegateFunction<RetT
15501553
return false;
15511554

15521555
// Protect data shared between source and destination threads
1553-
const std::lock_guard<Mutex> lock(delegateMsg->GetLock());
1556+
const dmq::LockGuard<Mutex> lock(delegateMsg->GetLock());
15541557

15551558
// Is the source thread waiting for the target function invoke to complete?
15561559
if (delegateMsg->GetInvokerWaiting()) {
@@ -1741,6 +1744,8 @@ auto MakeDelegate(F&& func, IThread& thread, Duration timeout) {
17411744
return DelegateFunctionAsyncWait<Sig>(std::forward<F>(func), thread, timeout);
17421745
}
17431746

1744-
}
1747+
}
1748+
1749+
#endif // DMQ_HAS_CV
17451750

17461751
#endif

DelegateMQ/delegate/DelegateOpt.h

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
/// @brief Delegate library options header file.
66

77
#include <chrono>
8-
#include <mutex>
8+
#if defined(DMQ_THREAD_STDLIB) || defined(DMQ_THREAD_WIN32) || defined(DMQ_THREAD_QT)
9+
#include <mutex>
10+
#endif
911

1012
// RTTI Detection Check
1113
#if !defined(__cpp_rtti) && !defined(__GXX_RTTI) && !defined(_CPPRTTI)
@@ -16,10 +18,12 @@
1618
// Windows / Linux / macOS / Qt (Standard Library)
1719
#include <condition_variable>
1820
#elif defined(DMQ_THREAD_FREERTOS)
21+
#include <mutex>
1922
#include "predef/util/FreeRTOSClock.h"
2023
#include "predef/util/FreeRTOSMutex.h"
2124
#include "predef/util/FreeRTOSConditionVariable.h"
2225
#elif defined(DMQ_THREAD_THREADX)
26+
#include <mutex>
2327
#include "predef/util/ThreadXClock.h"
2428
#include "predef/util/ThreadXMutex.h"
2529
#include "predef/util/ThreadXConditionVariable.h"
@@ -35,6 +39,18 @@
3539

3640
namespace dmq
3741
{
42+
// --- PORTABLE LOCK GUARD ---
43+
// Does not require <mutex>. Works with any BasicLockable type (lock/unlock).
44+
template<typename T>
45+
class PortableLockGuard {
46+
T& m_mutex;
47+
public:
48+
explicit PortableLockGuard(T& m) noexcept : m_mutex(m) { m_mutex.lock(); }
49+
~PortableLockGuard() noexcept { m_mutex.unlock(); }
50+
PortableLockGuard(const PortableLockGuard&) = delete;
51+
PortableLockGuard& operator=(const PortableLockGuard&) = delete;
52+
};
53+
3854
// @TODO: Change aliases to switch clock type globally if necessary
3955

4056
// --- CLOCK SELECTION ---
@@ -73,37 +89,50 @@ namespace dmq
7389
using Mutex = std::mutex;
7490
using RecursiveMutex = std::recursive_mutex;
7591
using ConditionVariable = std::condition_variable;
92+
template<typename T> using LockGuard = std::lock_guard<T>;
93+
template<typename T> using UniqueLock = std::unique_lock<T>;
94+
#define DMQ_HAS_CV
7695

7796
#elif defined(DMQ_THREAD_FREERTOS)
7897
// Use the custom FreeRTOS wrapper
7998
using Mutex = dmq::FreeRTOSMutex;
8099
using RecursiveMutex = dmq::FreeRTOSRecursiveMutex;
81100
using ConditionVariable = dmq::FreeRTOSConditionVariable;
101+
template<typename T> using LockGuard = PortableLockGuard<T>;
102+
template<typename T> using UniqueLock = std::unique_lock<T>;
103+
#define DMQ_HAS_CV
82104

83105
#elif defined(DMQ_THREAD_THREADX)
84106
// Use the custom ThreadX wrapper
85107
using Mutex = dmq::ThreadXMutex;
86108
using RecursiveMutex = dmq::ThreadXRecursiveMutex;
87109
using ConditionVariable = dmq::ThreadXConditionVariable;
110+
template<typename T> using LockGuard = PortableLockGuard<T>;
111+
template<typename T> using UniqueLock = std::unique_lock<T>;
112+
#define DMQ_HAS_CV
88113

89114
#elif defined(DMQ_THREAD_ZEPHYR)
90115
// Use the custom Zephyr wrapper
91116
using Mutex = dmq::ZephyrMutex;
92117
using RecursiveMutex = dmq::ZephyrRecursiveMutex;
118+
template<typename T> using LockGuard = PortableLockGuard<T>;
93119

94120
#elif defined(DMQ_THREAD_CMSIS_RTOS2)
95121
using Mutex = dmq::CmsisRtos2Mutex;
96122
using RecursiveMutex = dmq::CmsisRtos2RecursiveMutex;
123+
template<typename T> using LockGuard = PortableLockGuard<T>;
97124

98125
#else
99126
// Bare metal has no threads, so no locking is required.
100-
// We define a dummy "No-Op" mutex.
127+
// NullMutex satisfies BasicLockable; PortableLockGuard compiles to nothing meaningful.
101128
struct NullMutex {
102129
void lock() {}
103130
void unlock() {}
104131
};
105132
using Mutex = NullMutex;
106133
using RecursiveMutex = NullMutex;
134+
template<typename T> using LockGuard = PortableLockGuard<T>;
135+
// No DMQ_HAS_CV — Semaphore and DelegateAsyncWait are unavailable on bare metal
107136
#endif
108137
}
109138

@@ -163,7 +192,6 @@ namespace dmq
163192
typedef std::basic_stringstream<char, std::char_traits<char>> xstringstream;
164193

165194
typedef std::string xstring;
166-
typedef std::wstring xwstring;
167195

168196
// Fallback xmake_shared — uses std::make_shared when fixed-block allocator is disabled
169197
template <typename T, typename... Args>

DelegateMQ/delegate/MulticastDelegateSafe.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,43 +47,43 @@ class MulticastDelegateSafe<RetType(Args...)> : public MulticastDelegate<RetType
4747
/// A void return value is used since multiple targets invoked.
4848
/// @param[in] args The arguments used when invoking the target functions
4949
void operator()(Args... args) {
50-
const std::lock_guard<RecursiveMutex> lock(m_lock);
50+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
5151
BaseType::operator ()(args...);
5252
}
5353

5454
/// Invoke all bound target functions. A void return value is used
5555
/// since multiple targets invoked.
5656
/// @param[in] args The arguments used when invoking the target functions
5757
void Broadcast(Args... args) {
58-
const std::lock_guard<RecursiveMutex> lock(m_lock);
58+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
5959
BaseType::Broadcast(args...);
6060
}
6161

6262
/// Insert a delegate into the container.
6363
/// @param[in] delegate A delegate target to insert
6464
void operator+=(const Delegate<RetType(Args...)>& delegate) {
65-
const std::lock_guard<RecursiveMutex> lock(m_lock);
65+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
6666
BaseType::operator +=(delegate);
6767
}
6868

6969
/// Insert a delegate into the container.
7070
/// @param[in] delegate A delegate target to insert
7171
void operator+=(Delegate<RetType(Args...)>&& delegate) {
72-
const std::lock_guard<RecursiveMutex> lock(m_lock);
72+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
7373
BaseType::operator +=(delegate);
7474
}
7575

7676
/// Remove a delegate from the container.
7777
/// @param[in] delegate A delegate target to remove
7878
void operator-=(const Delegate<RetType(Args...)>& delegate) {
79-
const std::lock_guard<RecursiveMutex> lock(m_lock);
79+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
8080
BaseType::operator -=(delegate);
8181
}
8282

8383
/// Remove a delegate from the container.
8484
/// @param[in] delegate A delegate target to remove
8585
void operator-=(Delegate<RetType(Args...)>&& delegate) {
86-
const std::lock_guard<RecursiveMutex> lock(m_lock);
86+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
8787
BaseType::operator -=(delegate);
8888
}
8989

@@ -112,48 +112,48 @@ class MulticastDelegateSafe<RetType(Args...)> : public MulticastDelegate<RetType
112112

113113
/// @brief Clear the all target functions.
114114
virtual void operator=(std::nullptr_t) noexcept {
115-
const std::lock_guard<RecursiveMutex> lock(m_lock);
115+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
116116
BaseType::Clear();
117117
}
118118

119119
/// Insert a delegate into the container.
120120
/// @param[in] delegate A delegate target to insert
121121
void PushBack(const DelegateType& delegate) {
122-
const std::lock_guard<RecursiveMutex> lock(m_lock);
122+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
123123
BaseType::PushBack(delegate);
124124
}
125125

126126
/// Remove a delegate into the container.
127127
/// @param[in] delegate The delegate target to remove.
128128
void Remove(const DelegateType& delegate) {
129-
const std::lock_guard<RecursiveMutex> lock(m_lock);
129+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
130130
BaseType::Remove(delegate);
131131
}
132132

133133
/// Any registered delegates?
134134
/// @return `true` if delegate container is empty.
135135
bool Empty() const {
136-
const std::lock_guard<RecursiveMutex> lock(m_lock);
136+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
137137
return BaseType::Empty();
138138
}
139139

140140
/// Removal all registered delegates.
141141
void Clear() {
142-
const std::lock_guard<RecursiveMutex> lock(m_lock);
142+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
143143
BaseType::Clear();
144144
}
145145

146146
/// Get the number of delegates stored.
147147
/// @return The number of delegates stored.
148148
std::size_t Size() const {
149-
const std::lock_guard<RecursiveMutex> lock(m_lock);
149+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
150150
return BaseType::Size();
151151
}
152152

153153
/// @brief Implicit conversion operator to `bool`.
154154
/// @return `true` if the container is not empty, `false` if the container is empty.
155155
explicit operator bool() const {
156-
const std::lock_guard<RecursiveMutex> lock(m_lock);
156+
const dmq::LockGuard<RecursiveMutex> lock(m_lock);
157157
return BaseType::operator bool();
158158
}
159159

DelegateMQ/delegate/Semaphore.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include "DelegateOpt.h"
88

9+
#ifdef DMQ_HAS_CV
10+
911
// Fix compiler error on Windows
1012
#undef max
1113

@@ -23,7 +25,7 @@ class Semaphore
2325
/// @return Return true if semaphore signaled, false if timeout occurred.
2426
bool Wait(Duration timeout)
2527
{
26-
std::unique_lock<dmq::Mutex> lk(m_lock);
28+
dmq::UniqueLock<dmq::Mutex> lk(m_lock);
2729
if (timeout == Duration::max())
2830
{
2931
m_sema.wait(lk, [this] { return m_signaled; });
@@ -51,7 +53,7 @@ class Semaphore
5153
void Signal()
5254
{
5355
{
54-
std::unique_lock<dmq::Mutex> lk(m_lock);
56+
dmq::UniqueLock<dmq::Mutex> lk(m_lock);
5557
m_signaled = true;
5658
}
5759
m_sema.notify_one();
@@ -69,4 +71,6 @@ class Semaphore
6971

7072
}
7173

72-
#endif
74+
#endif // DMQ_HAS_CV
75+
76+
#endif

0 commit comments

Comments
 (0)