Delegated condition_variable against spurious wakeup

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












This is my attempt at dealing with spurious wakeups: A new class which replaced std::condition_variable in my code.



Some questions which came to my mind are (and I hope CR is the right place for that):



  1. Is this actually effective? Or will I run into concurrency-related problems?

  2. Would inheriting std::condition_variable be better than delegation?

  3. Is it better to use bool guarded by a std::mutex or std::atomic<bool>?

This is the class:



#include <mutex>
#include <condition_variable>

class Condition
private:
std::condition_variable _condition; // Delegation
bool _waiting;
std::mutex _internalMutex;
public:
Condition()
: _waiting(false)

void wait(std::unique_lock<std::mutex>& lock)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait(lock, [this]() return !_waiting; );


template< class Rep, class Period >
void wait_for(std::unique_lock<std::mutex>& lock,
const std::chrono::duration<Rep, Period>& relTime)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait_for(lock, relTime, [this]() return !_waiting; );


template< class Clock, class Duration >
void wait_until(std::unique_lock<std::mutex>& lock,
const std::chrono::time_point<Clock, Duration>& timeoutTime)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait_until(lock, timeoutTime, [this]() return !_waiting; );


void notify_all()

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = false;
_condition.notify_all();


void notify_one()

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = false;
_condition.notify_one();

;


The usage would be the same as with std::condition_variable (but without the typical caveat that you have to prevent spurious wakeups by encapsulating .wait() with a predicate check.







share|improve this question





















  • Right now, if the wait_until times out before any notify_X, doesn't _waiting remain true? I feel like using a single boolean to represent every thread results in inconsistent state.
    – svenevs
    Jan 4 at 23:48










  • @sjm324 That is right, to keep the code extendable, I will set _waiting back to false. But it shouldn't change the current behavior as the flag is only evaluated directly after it has been set to true anyways, does it?
    – PhilLab
    Jan 5 at 9:02











  • It probably doesn't matter, I think setting it to false would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threads A and B both wait(). Then notify_one() is issued, and A got woken up. At this point, _waiting is false. So if B gets spuriously woken up at this point, it will get unleashed because the notify_one() set _waiting to false for everybody. Is this what you want, or the opposite? If the opposite, this is why one boolean cannot represent them all.
    – svenevs
    Jan 5 at 10:00










  • @sjm324 okay, as i never use notify_one() I should probably just remove it entirely and then actually as you said not set _wait to false
    – PhilLab
    Jan 5 at 14:07










  • the first big issue with my code is that it actually never locked the mutex. Edited my post to fix this
    – PhilLab
    Jan 8 at 13:55
















up vote
4
down vote

favorite












This is my attempt at dealing with spurious wakeups: A new class which replaced std::condition_variable in my code.



Some questions which came to my mind are (and I hope CR is the right place for that):



  1. Is this actually effective? Or will I run into concurrency-related problems?

  2. Would inheriting std::condition_variable be better than delegation?

  3. Is it better to use bool guarded by a std::mutex or std::atomic<bool>?

This is the class:



#include <mutex>
#include <condition_variable>

class Condition
private:
std::condition_variable _condition; // Delegation
bool _waiting;
std::mutex _internalMutex;
public:
Condition()
: _waiting(false)

void wait(std::unique_lock<std::mutex>& lock)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait(lock, [this]() return !_waiting; );


template< class Rep, class Period >
void wait_for(std::unique_lock<std::mutex>& lock,
const std::chrono::duration<Rep, Period>& relTime)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait_for(lock, relTime, [this]() return !_waiting; );


template< class Clock, class Duration >
void wait_until(std::unique_lock<std::mutex>& lock,
const std::chrono::time_point<Clock, Duration>& timeoutTime)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait_until(lock, timeoutTime, [this]() return !_waiting; );


void notify_all()

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = false;
_condition.notify_all();


void notify_one()

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = false;
_condition.notify_one();

;


The usage would be the same as with std::condition_variable (but without the typical caveat that you have to prevent spurious wakeups by encapsulating .wait() with a predicate check.







share|improve this question





















  • Right now, if the wait_until times out before any notify_X, doesn't _waiting remain true? I feel like using a single boolean to represent every thread results in inconsistent state.
    – svenevs
    Jan 4 at 23:48










  • @sjm324 That is right, to keep the code extendable, I will set _waiting back to false. But it shouldn't change the current behavior as the flag is only evaluated directly after it has been set to true anyways, does it?
    – PhilLab
    Jan 5 at 9:02











  • It probably doesn't matter, I think setting it to false would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threads A and B both wait(). Then notify_one() is issued, and A got woken up. At this point, _waiting is false. So if B gets spuriously woken up at this point, it will get unleashed because the notify_one() set _waiting to false for everybody. Is this what you want, or the opposite? If the opposite, this is why one boolean cannot represent them all.
    – svenevs
    Jan 5 at 10:00










  • @sjm324 okay, as i never use notify_one() I should probably just remove it entirely and then actually as you said not set _wait to false
    – PhilLab
    Jan 5 at 14:07










  • the first big issue with my code is that it actually never locked the mutex. Edited my post to fix this
    – PhilLab
    Jan 8 at 13:55












up vote
4
down vote

favorite









up vote
4
down vote

favorite











This is my attempt at dealing with spurious wakeups: A new class which replaced std::condition_variable in my code.



Some questions which came to my mind are (and I hope CR is the right place for that):



  1. Is this actually effective? Or will I run into concurrency-related problems?

  2. Would inheriting std::condition_variable be better than delegation?

  3. Is it better to use bool guarded by a std::mutex or std::atomic<bool>?

This is the class:



#include <mutex>
#include <condition_variable>

class Condition
private:
std::condition_variable _condition; // Delegation
bool _waiting;
std::mutex _internalMutex;
public:
Condition()
: _waiting(false)

void wait(std::unique_lock<std::mutex>& lock)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait(lock, [this]() return !_waiting; );


template< class Rep, class Period >
void wait_for(std::unique_lock<std::mutex>& lock,
const std::chrono::duration<Rep, Period>& relTime)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait_for(lock, relTime, [this]() return !_waiting; );


template< class Clock, class Duration >
void wait_until(std::unique_lock<std::mutex>& lock,
const std::chrono::time_point<Clock, Duration>& timeoutTime)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait_until(lock, timeoutTime, [this]() return !_waiting; );


void notify_all()

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = false;
_condition.notify_all();


void notify_one()

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = false;
_condition.notify_one();

;


The usage would be the same as with std::condition_variable (but without the typical caveat that you have to prevent spurious wakeups by encapsulating .wait() with a predicate check.







share|improve this question













This is my attempt at dealing with spurious wakeups: A new class which replaced std::condition_variable in my code.



Some questions which came to my mind are (and I hope CR is the right place for that):



  1. Is this actually effective? Or will I run into concurrency-related problems?

  2. Would inheriting std::condition_variable be better than delegation?

  3. Is it better to use bool guarded by a std::mutex or std::atomic<bool>?

This is the class:



#include <mutex>
#include <condition_variable>

class Condition
private:
std::condition_variable _condition; // Delegation
bool _waiting;
std::mutex _internalMutex;
public:
Condition()
: _waiting(false)

void wait(std::unique_lock<std::mutex>& lock)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait(lock, [this]() return !_waiting; );


template< class Rep, class Period >
void wait_for(std::unique_lock<std::mutex>& lock,
const std::chrono::duration<Rep, Period>& relTime)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait_for(lock, relTime, [this]() return !_waiting; );


template< class Clock, class Duration >
void wait_until(std::unique_lock<std::mutex>& lock,
const std::chrono::time_point<Clock, Duration>& timeoutTime)

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = true;
_condition.wait_until(lock, timeoutTime, [this]() return !_waiting; );


void notify_all()

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = false;
_condition.notify_all();


void notify_one()

std::unique_lock<std::mutex> lock(_internalMutex);
_waiting = false;
_condition.notify_one();

;


The usage would be the same as with std::condition_variable (but without the typical caveat that you have to prevent spurious wakeups by encapsulating .wait() with a predicate check.









share|improve this question












share|improve this question




share|improve this question








edited Jan 8 at 13:54
























asked Jan 4 at 18:29









PhilLab

1213




1213











  • Right now, if the wait_until times out before any notify_X, doesn't _waiting remain true? I feel like using a single boolean to represent every thread results in inconsistent state.
    – svenevs
    Jan 4 at 23:48










  • @sjm324 That is right, to keep the code extendable, I will set _waiting back to false. But it shouldn't change the current behavior as the flag is only evaluated directly after it has been set to true anyways, does it?
    – PhilLab
    Jan 5 at 9:02











  • It probably doesn't matter, I think setting it to false would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threads A and B both wait(). Then notify_one() is issued, and A got woken up. At this point, _waiting is false. So if B gets spuriously woken up at this point, it will get unleashed because the notify_one() set _waiting to false for everybody. Is this what you want, or the opposite? If the opposite, this is why one boolean cannot represent them all.
    – svenevs
    Jan 5 at 10:00










  • @sjm324 okay, as i never use notify_one() I should probably just remove it entirely and then actually as you said not set _wait to false
    – PhilLab
    Jan 5 at 14:07










  • the first big issue with my code is that it actually never locked the mutex. Edited my post to fix this
    – PhilLab
    Jan 8 at 13:55
















  • Right now, if the wait_until times out before any notify_X, doesn't _waiting remain true? I feel like using a single boolean to represent every thread results in inconsistent state.
    – svenevs
    Jan 4 at 23:48










  • @sjm324 That is right, to keep the code extendable, I will set _waiting back to false. But it shouldn't change the current behavior as the flag is only evaluated directly after it has been set to true anyways, does it?
    – PhilLab
    Jan 5 at 9:02











  • It probably doesn't matter, I think setting it to false would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threads A and B both wait(). Then notify_one() is issued, and A got woken up. At this point, _waiting is false. So if B gets spuriously woken up at this point, it will get unleashed because the notify_one() set _waiting to false for everybody. Is this what you want, or the opposite? If the opposite, this is why one boolean cannot represent them all.
    – svenevs
    Jan 5 at 10:00










  • @sjm324 okay, as i never use notify_one() I should probably just remove it entirely and then actually as you said not set _wait to false
    – PhilLab
    Jan 5 at 14:07










  • the first big issue with my code is that it actually never locked the mutex. Edited my post to fix this
    – PhilLab
    Jan 8 at 13:55















Right now, if the wait_until times out before any notify_X, doesn't _waiting remain true? I feel like using a single boolean to represent every thread results in inconsistent state.
– svenevs
Jan 4 at 23:48




Right now, if the wait_until times out before any notify_X, doesn't _waiting remain true? I feel like using a single boolean to represent every thread results in inconsistent state.
– svenevs
Jan 4 at 23:48












@sjm324 That is right, to keep the code extendable, I will set _waiting back to false. But it shouldn't change the current behavior as the flag is only evaluated directly after it has been set to true anyways, does it?
– PhilLab
Jan 5 at 9:02





@sjm324 That is right, to keep the code extendable, I will set _waiting back to false. But it shouldn't change the current behavior as the flag is only evaluated directly after it has been set to true anyways, does it?
– PhilLab
Jan 5 at 9:02













It probably doesn't matter, I think setting it to false would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threads A and B both wait(). Then notify_one() is issued, and A got woken up. At this point, _waiting is false. So if B gets spuriously woken up at this point, it will get unleashed because the notify_one() set _waiting to false for everybody. Is this what you want, or the opposite? If the opposite, this is why one boolean cannot represent them all.
– svenevs
Jan 5 at 10:00




It probably doesn't matter, I think setting it to false would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threads A and B both wait(). Then notify_one() is issued, and A got woken up. At this point, _waiting is false. So if B gets spuriously woken up at this point, it will get unleashed because the notify_one() set _waiting to false for everybody. Is this what you want, or the opposite? If the opposite, this is why one boolean cannot represent them all.
– svenevs
Jan 5 at 10:00












@sjm324 okay, as i never use notify_one() I should probably just remove it entirely and then actually as you said not set _wait to false
– PhilLab
Jan 5 at 14:07




@sjm324 okay, as i never use notify_one() I should probably just remove it entirely and then actually as you said not set _wait to false
– PhilLab
Jan 5 at 14:07












the first big issue with my code is that it actually never locked the mutex. Edited my post to fix this
– PhilLab
Jan 8 at 13:55




the first big issue with my code is that it actually never locked the mutex. Edited my post to fix this
– PhilLab
Jan 8 at 13:55















active

oldest

votes











Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184301%2fdelegated-condition-variable-against-spurious-wakeup%23new-answer', 'question_page');

);

Post as a guest



































active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes










 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184301%2fdelegated-condition-variable-against-spurious-wakeup%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Greedy Best First Search implementation in Rust

Function to Return a JSON Like Objects Using VBA Collections and Arrays

C++11 CLH Lock Implementation