Skip to content
Snippets Groups Projects
Commit 1d5fc6d3 authored by Florian Schmaus's avatar Florian Schmaus
Browse files

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!
parent fbe088fc
No related branches found
No related tags found
No related merge requests found
......@@ -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);
}
......
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment