From 1d5fc6d3e335e0f97a1208c9626d38b30e57c7d0 Mon Sep 17 00:00:00 2001 From: Florian Schmaus <flow@cs.fau.de> Date: Thu, 3 Aug 2017 19:26:23 +0200 Subject: [PATCH] Add postRetrieve hook to UnboundedBlockingMpscQueue and use that hook in Actor. This fixes a race condition in the actor loop between 'queue.get()' and 'setState(Running)' racing against waitUntilIdle(long)'s check if queue.size() == 0 && state == Retrieving Because right after the get() operation is finished, the queue size is 0, but the state is not yet at Running, while the Actor actually is not idle. Thanks Raim! Best rubber duck ever! --- emper/Actor.hpp | 5 +++-- emper/UnboundedBlockingMpscQueue.hpp | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/emper/Actor.hpp b/emper/Actor.hpp index e4cc4296..9810fe61 100644 --- a/emper/Actor.hpp +++ b/emper/Actor.hpp @@ -32,9 +32,10 @@ private: while (state == Running) { setState(Retrieving); - T t = queue.get(); + T t = queue.get([this] { + setState(Running); + }); - setState(Running); receive(t); } diff --git a/emper/UnboundedBlockingMpscQueue.hpp b/emper/UnboundedBlockingMpscQueue.hpp index 293c78ab..c28449ab 100644 --- a/emper/UnboundedBlockingMpscQueue.hpp +++ b/emper/UnboundedBlockingMpscQueue.hpp @@ -26,12 +26,13 @@ private: } } - void tryToGetElement() { + void tryToGetElement(std::function<void(void)> postRetrieve) { std::lock_guard<std::mutex> lock(queueMutex); if (!mpscQueue.empty()) { t = mpscQueue.front(); mpscQueue.pop(); tPopped = true; + postRetrieve(); } } @@ -57,16 +58,16 @@ public: } } - T get() { + T get(std::function<void(void)> postRetrieve) { tPopped = false; - tryToGetElement(); + tryToGetElement(postRetrieve); if (!tPopped) { Context* context = Context::getCurrentContext(); - block([this, context] { + block([this, context, postRetrieve] { blockedContext = context; - tryToGetElement(); + tryToGetElement(postRetrieve); if (tPopped) { tryToWakeupBlockedContext(); } @@ -79,6 +80,7 @@ public: assert(!mpscQueue.empty()); t = mpscQueue.front(); mpscQueue.pop(); + postRetrieve(); } } return t; -- GitLab