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_variable
be better than delegation? - Is it better to use
bool
guarded by astd::mutex
orstd::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_variable
be better than delegation? - Is it better to use
bool
guarded by astd::mutex
orstd::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_until
times out before anynotify_X
, doesn't_waiting
remaintrue
? 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 tofalse
would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threadsA
andB
bothwait()
. Thennotify_one()
is issued, andA
got woken up. At this point,_waiting
isfalse
. So ifB
gets spuriously woken up at this point, it will get unleashed because thenotify_one()
set_waiting
tofalse
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 usenotify_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
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_variable
be better than delegation? - Is it better to use
bool
guarded by astd::mutex
orstd::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_variable
be better than delegation? - Is it better to use
bool
guarded by astd::mutex
orstd::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_until
times out before anynotify_X
, doesn't_waiting
remaintrue
? 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 tofalse
would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threadsA
andB
bothwait()
. Thennotify_one()
is issued, andA
got woken up. At this point,_waiting
isfalse
. So ifB
gets spuriously woken up at this point, it will get unleashed because thenotify_one()
set_waiting
tofalse
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 usenotify_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
add a comment |Â
Right now, if thewait_until
times out before anynotify_X
, doesn't_waiting
remaintrue
? 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 tofalse
would be "worse". The context of your question is about spurious wakeups, so I wonder what the goal is. Suppose threadsA
andB
bothwait()
. Thennotify_one()
is issued, andA
got woken up. At this point,_waiting
isfalse
. So ifB
gets spuriously woken up at this point, it will get unleashed because thenotify_one()
set_waiting
tofalse
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 usenotify_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
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_until
times out before anynotify_X
, doesn't_waiting
remaintrue
? 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 threadsA
andB
bothwait()
. Thennotify_one()
is issued, andA
got woken up. At this point,_waiting
isfalse
. So ifB
gets spuriously woken up at this point, it will get unleashed because thenotify_one()
set_waiting
tofalse
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