Delegated condition_variable against spurious wakeup

Clash 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):
- Is this actually effective? Or will I run into concurrency-related problems?
- Would inheriting
std::condition_variablebe better than delegation? - Is it better to use
boolguarded by astd::mutexorstd::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.
c++ c++11 multithreading locking
add a comment |Â
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):
- Is this actually effective? Or will I run into concurrency-related problems?
- Would inheriting
std::condition_variablebe better than delegation? - Is it better to use
boolguarded by astd::mutexorstd::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.
c++ c++11 multithreading locking
Right now, if thewait_untiltimes out before anynotify_X, doesn't_waitingremaintrue? 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_waitingback 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 tofalsewould be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threadsAandBbothwait(). Thennotify_one()is issued, andAgot woken up. At this point,_waitingisfalse. So ifBgets spuriously woken up at this point, it will get unleashed because thenotify_one()set_waitingtofalsefor 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 usenotify_one()I should probably just remove it entirely and then actually as you said not set_waitto 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
add a comment |Â
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):
- Is this actually effective? Or will I run into concurrency-related problems?
- Would inheriting
std::condition_variablebe better than delegation? - Is it better to use
boolguarded by astd::mutexorstd::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.
c++ c++11 multithreading locking
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):
- Is this actually effective? Or will I run into concurrency-related problems?
- Would inheriting
std::condition_variablebe better than delegation? - Is it better to use
boolguarded by astd::mutexorstd::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.
c++ c++11 multithreading locking
edited Jan 8 at 13:54
asked Jan 4 at 18:29
PhilLab
1213
1213
Right now, if thewait_untiltimes out before anynotify_X, doesn't_waitingremaintrue? 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_waitingback 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 tofalsewould be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threadsAandBbothwait(). Thennotify_one()is issued, andAgot woken up. At this point,_waitingisfalse. So ifBgets spuriously woken up at this point, it will get unleashed because thenotify_one()set_waitingtofalsefor 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 usenotify_one()I should probably just remove it entirely and then actually as you said not set_waitto 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
add a comment |Â
Right now, if thewait_untiltimes out before anynotify_X, doesn't_waitingremaintrue? 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_waitingback 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 tofalsewould be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threadsAandBbothwait(). Thennotify_one()is issued, andAgot woken up. At this point,_waitingisfalse. So ifBgets spuriously woken up at this point, it will get unleashed because thenotify_one()set_waitingtofalsefor 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 usenotify_one()I should probably just remove it entirely and then actually as you said not set_waitto 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
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Right now, if the
wait_untiltimes out before anynotify_X, doesn't_waitingremaintrue? 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
_waitingback 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
falsewould be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threadsAandBbothwait(). Thennotify_one()is issued, andAgot woken up. At this point,_waitingisfalse. So ifBgets spuriously woken up at this point, it will get unleashed because thenotify_one()set_waitingtofalsefor 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_waitto 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