Necesito dos hilos para avanzar en un patrón "tic tock". Cuando implmented con un semáforo esto se ve bien:¿Usar un mutex como semáforo?
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);
}
}
Sin embargo, si hago lo mismo con un mutex (que es técnicamente un semáforo binario), que tiene un olor extraño código.
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();
}
}
Creo que el olor es que un mutex no está destinado a transmitir información a otro hilo. (El comité estándar de C++ 11 agregó un falso error al try_lock para vencer la transferencia de información inesperada; §30.4.1/14.) Parece que los mutexes están destinados a sincronizar el acceso a una variable, que luego puede transmitir información a otro hilo.
Por último, cuando se implementa con un std::condition_variable
, parece correcto, pero es más complicado (una variable tick_vs_tock, un mutex y una variable de condición). He omitido la implementación por brevedad, pero es realmente sencillo.
¿La solución mutex está bien? ¿O hay algo sutilmente mal con eso?
¿Hay un buen patrón para resolver mi problema de tic/tac que no he pensado?
BTW: este problema solo surgió porque C++ 0x no tiene un 'std :: semáforo' y la doble solución' std :: mutex' es menos complicada que la solución 'std :: condition_variable'. –
(¿Por qué) es incluso válido para 'desbloquear()' un mutex en un hilo que no lo contiene actualmente? –
@Steve esa es realmente una buena pregunta (sugerencia, sugerencia, empujoncito, empujón). –