web-dev-qa-db-fra.com

attente du fil jusqu'à ce qu'une condition soit apparue

Je veux attendre qu'un thread de 2 threads exécuté dans un simulateur simultané jusqu'à ce qu'une condition soit apparue. Cette condition peut être apparue après 1000 cycles ou plus d'exécution d'un programme dans le simulateur. Comment puis-je le faire?

20
Angelia Wikin

Vous avez besoin de variables conditionnelles.

Si votre compilateur supporte std::conditional introduit par C++ 11, vous pouvez le voir pour plus de détails:

Si votre compilateur ne le supporte pas et que vous travaillez avec des threads win32, voyez ceci:

Et ici est un exemple complet.

Et si vous travaillez avec des threads POSIX, voyez ceci:


Vous pouvez voir mon implémentation de conditional_variable en utilisant les primitives win32 ici:

Faites défiler l'écran vers le bas et voyez d'abord son implémentation, puis voyez l'utilisation dans l'implémentation de la file d'attente simultanée.

Une utilisation typique de variable conditionnelle est la suivante:

//lock the mutex first!
scoped_lock myLock(myMutex); 

//wait till a condition is met
myConditionalVariable.wait(myLock, CheckCondition);

//Execute this code only if the condition is met

CheckCondition est une fonction (ou un foncteur) qui vérifie la condition. Elle est appelée en interne par la fonction wait() lorsqu'elle de façon éhontée se réveille et si la condition n'est pas encore remplie, la fonction wait() se met en veille. Avant de dormir, wait() libère le mutex, atomiquement.

32
Nawaz

Si vous n'avez pas C++ 11, mais que vous avez un système qui prend en charge les threads POSIX, vous pouvez utiliser une variable de condition. Il existe d'autres choix, mais une variable de condition peut être la plus simple, compte tenu de la façon dont vous avez décrit votre problème.

Une variable de condition pthread est utilisée conjointement avec un mutex. Le truc avec la variable de condition est que l’attente provoque la libération du mutex acquis, jusqu’au retour de l’appel d’attente, date à laquelle le mutex a de nouveau été acquis. La séquence est:

  • acquérir mutex
  • alors que PREDICATE n'est pas vrai
    • attendre la variable de condition
  • travaille sur la section critique
  • si PREDICATE est vrai
    • variable d'état du signal
  • libérer le mutex

L'étape de signal est utilisée dans le cas où plusieurs threads entrent dans la même section critique ci-dessus.

Si un thread différent peut accéder au même mutex pour modifier l'état qui affecte le PREDICATE, ce thread doit vérifier si quelqu'un doit être signalé.

  • acquérir mutex
  • travaille sur la section critique
  • si PREDICATE est vrai
    • variable d'état du signal
  • libérer le mutex

Les commandes POSIX d’intérêt sont:

pthread_mutex_init()
pthread_mutex_destroy()
pthread_mutex_lock()
pthread_mutex_unlock()
pthread_cond_init()
pthread_cond_destroy()
pthread_cond_wait()
pthread_cond_signal()
6
jxh

Utilisation de Semaphore pour la signalisation. Exemple (sortie propre de l'application) comme ci-dessous:

Déclarer en tête

static sem_t semPrepareExit;            //declaration

En source (filetage principal);

sem_init(&semPrepareExit, 0, 0);        ///semaphore initialized
...
///now wait for the signal on the semaphore, to proceed hereforth
sem_post(&semPrepareExit);
/// cleanup ahead
...

Dans la source, (spawned-thread);

...
sem_post(&semPrepareExit);

Maintenant, dès que vous signalez le sémaphore en utilisant "sem_post". Le thread principal recevra le signal au noeud/point d'attente et procédera par la suite.

1
parasrish

essayez quelque chose comme ça:

class CmyClass
{
   boost::mutex mtxEventWait;
   bool WaitForEvent(long milliseconds);
   boost::condition cndSignalEvent;
};

bool CmyClass::WaitForEvent(long milliseconds)
{
   boost::mutex::scoped_lock mtxWaitLock(mtxEventWait);
   boost::posix_time::time_duration wait_duration = boost::posix_time::milliseconds(milliseconds); 
   boost::system_time const timeout=boost::get_system_time()+wait_duration; 
   return cndSignalEvent.timed_wait(mtxEventWait,timeout); // wait until signal Event 
}

// afin d'attendre puis appeler la méthode WaitForEvent

WaitForEvent(1000); // it will timeout after 1 second

// voici comment un événement pourrait être signalé:

cndSignalEvent.notify_one();
1
serup