I need two threads to progress in a "tick tock" pattern. When implmented with a semaphore this looks fine:
Semaphore tick_sem(1);
Semaphore tock_sem(0);
void ticker( void )
{
while( true )
{
P( tick_sem );
do_tick();
V( tock_sem );
}
}
void tocker( void )
{
while( true )
{
P( tock_sem );
do_tock();
V( tick_sem );
}
}
However, if I do the same thing with a mutex ( which is technically a binary semaphore ), it has an odd code smell.
std::mutex tick_mutex;
std::mutex tock_mutex;
tock_mutex.lock();
void ticker( void )
{
while( true )
{
tick_mutex.lock();
do_tick();
tock_mutex.unlock();
}
}
void tocker( void )
{
while( true )
{
tock_mutex.lock()
do_tock();
tick_mutex.unlock();
}
}
I think the smell is that a mutex isn't meant to convey information to another thread. (The c++11 standard committee added a spurious fail to try_lock to defeat unexpected information transfer; §30.4.1/14.) It seems like mutexes are meant to synchronize access to a variable, which can then convey information to another thread.
Lastly, when implemented with a std::condition_variable
, it looks correct but it's more complicated ( a tick_vs_tock variable, a mutex, and a condition variable). I've omitted the implementation for brevity, but it's really straight forward.
Is the mutex solution fine? Or is there something subtly wrong with it?
Is there a good pattern for solving my tick/tock problem that I haven't thought of?
std::semaphore
and the doublestd::mutex
solution is less complicated than thestd::condition_variable
solution. – Betunlock()
a mutex in a thread that doesn't currently hold it? – Nessim