Las variables condicionales son NO el equivalente de AutoResetEvent. Son el equivalente a los Monitores. La diferencia es crítica y puede causar interbloqueos si no se usa correctamente:
Imagine dos subprocesos A y B en un programa C#. A llama a WaitOne() y B llama a Set(). Si B ejecuta Set() antes de que A alcance la llamada a WaitOne(), no hay problema porque la señal enviada a AutoResetEvent() por Set() es persistente y permanecerá establecida hasta que se ejecute WaitOne().
Ahora en C, imagina dos subprocesos C y D. C llama a esperar (), D llama a notificar (). Si C ya está esperando cuando D llama a notificar () todo está bien. Si C no logró llegar a esperar () antes de que D llame a notificar (), tiene un punto muerto porque la señal se pierde si nadie la está esperando y el estado de la variable condicional aún está "desestablecido".
Ten mucho cuidado con esto.
Estoy bastante seguro de que estás buscando variables de condición. La respuesta aceptada a esta otra pregunta SO:Variables de condición en C#, parece confirmarlo.
Véase, por ejemplo. este tutorial para obtener detalles sobre las variables de condición en hilos POSIX.
Un AutoResetEvent es más parecido a un semáforo binario. Las personas que dicen "variables condicionales" no están equivocadas per se, pero las variables de condición se usan en situaciones similares, en lugar de ser objetos similares. Puede implementar un AutoResetEvent (sin nombre) sobre las variables de condición:
#include <pthread.h>
#include <stdio.h>
class AutoResetEvent
{
public:
explicit AutoResetEvent(bool initial = false);
~AutoResetEvent();
void Set();
void Reset();
bool WaitOne();
private:
AutoResetEvent(const AutoResetEvent&);
AutoResetEvent& operator=(const AutoResetEvent&); // non-copyable
bool flag_;
pthread_mutex_t protect_;
pthread_cond_t signal_;
};
AutoResetEvent::AutoResetEvent(bool initial)
: flag_(initial)
{
pthread_mutex_init(&protect_, NULL);
pthread_cond_init(&signal_, NULL);
}
void AutoResetEvent::Set()
{
pthread_mutex_lock(&protect_);
flag_ = true;
pthread_mutex_unlock(&protect_);
pthread_cond_signal(&signal_);
}
void AutoResetEvent::Reset()
{
pthread_mutex_lock(&protect_);
flag_ = false;
pthread_mutex_unlock(&protect_);
}
bool AutoResetEvent::WaitOne()
{
pthread_mutex_lock(&protect_);
while( !flag_ ) // prevent spurious wakeups from doing harm
pthread_cond_wait(&signal_, &protect_);
flag_ = false; // waiting resets the flag
pthread_mutex_unlock(&protect_);
return true;
}
AutoResetEvent::~AutoResetEvent()
{
pthread_mutex_destroy(&protect_);
pthread_cond_destroy(&signal_);
}
AutoResetEvent event;
void *otherthread(void *)
{
event.WaitOne();
printf("Hello from other thread!\n");
return NULL;
}
int main()
{
pthread_t h;
pthread_create(&h, NULL, &otherthread, NULL);
printf("Hello from the first thread\n");
event.Set();
pthread_join(h, NULL);
return 0;
}
Sin embargo, si necesita eventos de restablecimiento automático con nombre, es probable que desee ver los semáforos y puede tener un poco más de dificultad para traducir su código. De cualquier manera, miraría con cuidado la documentación de pthreads en su plataforma, las variables de condición y los eventos de reinicio automático no son lo mismo y no se comportan de la misma manera.