@@ -78,12 +78,21 @@ namespace Aws
7878 * The first call moves the handle out and returns it; any subsequent call (including
7979 * calls after the OnPublishReceivedHandler callback returns) returns nullptr because
8080 * the ScopedResource is null after the move.
81+ *
82+ * A mutex handles race condition if two or more threads attempt to acquire control
83+ * of the same publish acknowledgement. One gets the non-null handle and the
84+ * other/s get nullptr.
8185 */
8286 struct PublishAcknowledgementFunctor
8387 {
88+ std::mutex mutex;
8489 ScopedResource<PublishAcknowledgementHandle> handle;
8590
86- ScopedResource<PublishAcknowledgementHandle> operator ()() { return std::move (handle); }
91+ ScopedResource<PublishAcknowledgementHandle> operator ()()
92+ {
93+ std::lock_guard<std::mutex> lock (mutex);
94+ return std::move (handle);
95+ }
8796 };
8897
8998 void Mqtt5ClientCore::s_lifeCycleEventCallback (const struct aws_mqtt5_client_lifecycle_event *event)
@@ -259,8 +268,9 @@ namespace Aws
259268 client_core->m_allocator , publishAcknowledgementId);
260269 /* std::function requires a copyable callable so we wrap the move only functor
261270 * into a shared_ptr so the lambda can be copyable. */
262- auto sharedFunctor = Aws::Crt::MakeShared<PublishAcknowledgementFunctor>(
263- client_core->m_allocator , std::move (functor));
271+ auto sharedFunctor =
272+ Aws::Crt::MakeShared<PublishAcknowledgementFunctor>(client_core->m_allocator );
273+ sharedFunctor->handle = std::move (functor.handle );
264274 eventData.acquirePublishAcknowledgement =
265275 [sharedFunctor]() -> ScopedResource<PublishAcknowledgementHandle>
266276 { return (*sharedFunctor)(); };
0 commit comments