4848// / * `std::function` compares the function signature type, not the underlying object instance.
4949// / See `DelegateFunction<>` class for more info.
5050// /
51- // / Code within `<common_code>` and `</common_code>` is updated using sync_src .py. Manually update
51+ // / Code within `<common_code>` and `</common_code>` is updated using src_dup .py. Manually update
5252// / the code within the `DelegateFreeAsyncWait` `common_code` tags, then run the script to
5353// / propagate to the remaining delegate classes to simplify code maintenance.
5454// /
@@ -172,7 +172,7 @@ class DelegateFreeAsyncWait<RetType(Args...)> : public DelegateFree<RetType(Args
172172 // / @brief Move constructor that transfers ownership of resources.
173173 // / @param[in] rhs The object to move from.
174174 DelegateFreeAsyncWait (ClassType&& rhs) noexcept :
175- BaseType (rhs), m_thread(rhs.m_thread), m_priority(rhs.m_priority), m_timeout(rhs.m_timeout), m_success(rhs.m_success), m_retVal(rhs.m_retVal) {
175+ BaseType (std::move( rhs) ), m_thread(rhs.m_thread), m_priority(rhs.m_priority), m_timeout(rhs.m_timeout), m_success(rhs.m_success), m_retVal(rhs.m_retVal) {
176176 rhs.Clear ();
177177 }
178178
@@ -302,7 +302,7 @@ class DelegateFreeAsyncWait<RetType(Args...)> : public DelegateFree<RetType(Args
302302 // / Use `IsSuccess()` to check for success before using the return value. Alternatively,
303303 // / use `AsyncInvoke()` and check the `std::optional` return value.
304304 // /
305- // / The `DelegateAsyncWaitMsg` does not duplicated and copy the function arguments into heap
305+ // / The `DelegateAsyncWaitMsg` does not duplicate and copy the function arguments into heap
306306 // / memory. The source thread waits on the destintation thread to complete, therefore argument
307307 // / data is shared between the source and destination threads and simultaneous access is prevented
308308 // / using a mutex.
@@ -338,8 +338,12 @@ class DelegateFreeAsyncWait<RetType(Args...)> : public DelegateFree<RetType(Args
338338 thread->DispatchDelegate (msg);
339339
340340 // Wait for destination thread to execute the delegate function and get return value
341- if ((m_success = msg->GetSema ().Wait (m_timeout)))
341+ if (msg->GetSema ().Wait (m_timeout)) {
342+ // Wait succeeded. Now acquire lock to safely read the value.
343+ const std::lock_guard<std::mutex> lock (msg->GetLock ());
344+ m_success = true ;
342345 m_retVal = delegate->m_retVal ;
346+ }
343347 }
344348
345349 // Protect data shared between source and destination threads
@@ -542,13 +546,13 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
542546 // / @brief Move constructor that transfers ownership of resources.
543547 // / @param[in] rhs The object to move from.
544548 DelegateMemberAsyncWait (ClassType&& rhs) noexcept :
545- BaseType (rhs), m_thread(rhs.m_thread), m_priority(rhs.m_priority), m_timeout(rhs.m_timeout), m_success(rhs.m_success), m_retVal(rhs.m_retVal) {
549+ BaseType (std::move( rhs) ), m_thread(rhs.m_thread), m_priority(rhs.m_priority), m_timeout(rhs.m_timeout), m_success(rhs.m_success), m_retVal(rhs.m_retVal) {
546550 rhs.Clear ();
547551 }
548552
549553 DelegateMemberAsyncWait () = default ;
550554
551- // / @brief Bind a const member function to the delegate.
555+ // / @brief Bind a member function to the delegate.
552556 // / @details This method associates a member function (`func`) with the delegate.
553557 // / Once the function is bound, the delegate can be used to invoke the function.
554558 // / @param[in] object The target object instance.
@@ -563,7 +567,7 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
563567 BaseType::Bind (object, func);
564568 }
565569
566- // / @brief Bind a member function to the delegate.
570+ // / @brief Bind a const member function to the delegate.
567571 // / @details This method associates a member function (`func`) with the delegate.
568572 // / Once the function is bound, the delegate can be used to invoke the function.
569573 // / @param[in] object The target object instance.
@@ -578,7 +582,7 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
578582 BaseType::Bind (object, func);
579583 }
580584
581- // / @brief Bind a const member function to the delegate.
585+ // / @brief Bind a member function to the delegate.
582586 // / @details This method associates a member function (`func`) with the delegate.
583587 // / Once the function is bound, the delegate can be used to invoke the function.
584588 // / @param[in] object The target object instance.
@@ -593,7 +597,7 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
593597 BaseType::Bind (object, func);
594598 }
595599
596- // / @brief Bind a member function to the delegate.
600+ // / @brief Bind a const member function to the delegate.
597601 // / @details This method associates a member function (`func`) with the delegate.
598602 // / Once the function is bound, the delegate can be used to invoke the function.
599603 // / @param[in] object The target object instance.
@@ -718,7 +722,7 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
718722 // / Use `IsSuccess()` to check for success before using the return value. Alternatively,
719723 // / use `AsyncInvoke()` and check the `std::optional` return value.
720724 // /
721- // / The `DelegateAsyncWaitMsg` does not duplicated and copy the function arguments into heap
725+ // / The `DelegateAsyncWaitMsg` does not duplicate and copy the function arguments into heap
722726 // / memory. The source thread waits on the destintation thread to complete, therefore argument
723727 // / data is shared between the source and destination threads and simultaneous access is prevented
724728 // / using a mutex.
@@ -754,8 +758,12 @@ class DelegateMemberAsyncWait<TClass, RetType(Args...)> : public DelegateMember<
754758 thread->DispatchDelegate (msg);
755759
756760 // Wait for destination thread to execute the delegate function and get return value
757- if ((m_success = msg->GetSema ().Wait (m_timeout)))
761+ if (msg->GetSema ().Wait (m_timeout)) {
762+ // Wait succeeded. Now acquire lock to safely read the value.
763+ const std::lock_guard<std::mutex> lock (msg->GetLock ());
764+ m_success = true ;
758765 m_retVal = delegate->m_retVal ;
766+ }
759767 }
760768
761769 // Protect data shared between source and destination threads
@@ -923,7 +931,7 @@ class DelegateFunctionAsyncWait<RetType(Args...)> : public DelegateFunction<RetT
923931 // / @brief Move constructor that transfers ownership of resources.
924932 // / @param[in] rhs The object to move from.
925933 DelegateFunctionAsyncWait (ClassType&& rhs) noexcept :
926- BaseType (rhs), m_thread(rhs.m_thread), m_priority(rhs.m_priority), m_timeout(rhs.m_timeout), m_success(rhs.m_success), m_retVal(rhs.m_retVal) {
934+ BaseType (std::move( rhs) ), m_thread(rhs.m_thread), m_priority(rhs.m_priority), m_timeout(rhs.m_timeout), m_success(rhs.m_success), m_retVal(rhs.m_retVal) {
927935 rhs.Clear ();
928936 }
929937
@@ -1053,7 +1061,7 @@ class DelegateFunctionAsyncWait<RetType(Args...)> : public DelegateFunction<RetT
10531061 // / Use `IsSuccess()` to check for success before using the return value. Alternatively,
10541062 // / use `AsyncInvoke()` and check the `std::optional` return value.
10551063 // /
1056- // / The `DelegateAsyncWaitMsg` does not duplicated and copy the function arguments into heap
1064+ // / The `DelegateAsyncWaitMsg` does not duplicate and copy the function arguments into heap
10571065 // / memory. The source thread waits on the destintation thread to complete, therefore argument
10581066 // / data is shared between the source and destination threads and simultaneous access is prevented
10591067 // / using a mutex.
@@ -1089,8 +1097,12 @@ class DelegateFunctionAsyncWait<RetType(Args...)> : public DelegateFunction<RetT
10891097 thread->DispatchDelegate (msg);
10901098
10911099 // Wait for destination thread to execute the delegate function and get return value
1092- if ((m_success = msg->GetSema ().Wait (m_timeout)))
1100+ if (msg->GetSema ().Wait (m_timeout)) {
1101+ // Wait succeeded. Now acquire lock to safely read the value.
1102+ const std::lock_guard<std::mutex> lock (msg->GetLock ());
1103+ m_success = true ;
10931104 m_retVal = delegate->m_retVal ;
1105+ }
10941106 }
10951107
10961108 // Protect data shared between source and destination threads
0 commit comments