Les variables conditionnelles ne sont PAS l'équivalent de AutoResetEvent. Ils sont l'équivalent des Moniteurs. La différence est critique et peut provoquer des interblocages si elle n'est pas utilisée correctement :
Imaginez deux threads A et B dans un programme C#. A appelle WaitOne() et B appelle Set(). Si B exécute Set() avant que A n'atteigne l'appel à WaitOne(), il n'y a pas de problème car le signal envoyé à AutoResetEvent() par Set() est persistant et il restera défini jusqu'à ce qu'un WaitOne() soit exécuté.
Maintenant en C, imaginez deux threads C et D. C appelle wait(), D appelle notify(). Si C attend déjà lorsque D appelle notify(), tout va bien. Si C n'a pas réussi à atteindre wait() avant que D n'appelle notify(), vous avez un interblocage car le signal est perdu si personne ne l'attend et que le statut de la variable conditionnelle est toujours "unset".
Soyez très prudent à ce sujet.
Je suis presque sûr que vous cherchez des variables de condition. La réponse acceptée à cette autre question SO :Variables de condition en C# -- semble le confirmer.
Voir par ex. ce tutoriel pour plus de détails sur les variables de condition dans les threads POSIX.
Un AutoResetEvent s'apparente le plus à un sémaphore binaire. Les personnes qui disent "variables conditionnelles" ne se trompent pas en soi, mais les variables de condition sont utilisées dans des situations similaires, plutôt que d'être des objets similaires. Vous pouvez implémenter un AutoResetEvent (sans nom) au-dessus des variables de condition :
#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;
}
Si toutefois, vous avez besoin d'événements de réinitialisation automatique nommés, vous souhaiterez probablement examiner les sémaphores et vous aurez peut-être un peu plus de mal à traduire votre code. Quoi qu'il en soit, je regarderais attentivement la documentation des pthreads sur votre plate-forme, les variables de condition et les événements de réinitialisation automatique ne sont pas les mêmes et ne se comportent pas de la même manière.