Le variabili condizionali sono NON l'equivalente di AutoResetEvent. Sono l'equivalente dei monitor. La differenza è critica e può causare deadlock se non utilizzata correttamente:
Immagina due thread A e B in un programma C#. A chiama WaitOne() e B chiama Set(). Se B esegue Set() prima che A raggiunga la chiamata a WaitOne(), non ci sono problemi perché il segnale inviato a AutoResetEvent() da Set() è persistente e rimarrà impostato finché non viene eseguito un WaitOne().
Ora in C, immagina due thread C e D. C chiama wait(), D chiama notify(). Se C è già in attesa quando D chiama notify(), va tutto bene. Se C non è riuscito a raggiungere wait() prima che D chiami notify(), hai un deadlock perché il segnale viene perso se nessuno lo sta aspettando e lo stato della variabile condizionale è ancora "non impostato".
Stai molto attento a questo.
Sono abbastanza sicuro che stai cercando variabili di condizione. La risposta accettata a quest'altra domanda SO:variabili di condizione in C# -- sembra confermarlo.
Vedi ad es. questo tutorial per i dettagli sulle variabili di condizione nei thread POSIX.
Un AutoResetEvent è molto simile a un semaforo binario. Le persone che dicono "variabili condizionali" non sono sbagliate di per sé, ma le variabili di condizione vengono utilizzate in situazioni simili, piuttosto che essere oggetti simili. Puoi implementare un AutoResetEvent (senza nome) sopra le variabili di condizione:
#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;
}
Se, tuttavia, hai bisogno di eventi di ripristino automatico denominati, probabilmente vorrai esaminare i semafori e potresti avere un po 'più di difficoltà a tradurre il tuo codice. In ogni caso, guarderei attentamente la documentazione per i pthread sulla tua piattaforma, le variabili di condizione e gli eventi di ripristino automatico non sono gli stessi e non si comportano allo stesso modo.