Je migre une applciation de Windows vers Linux. Je rencontre un problème concernant les interfaces WaitForSingleObject
et WaitForMultipleObjects
.
Dans mon application, je génère plusieurs threads où tous les threads attendent des événements du processus parent ou s'exécutent périodiquement toutes les t secondes.
J'ai vérifié pthread_cond_timedwait
, mais nous devons spécifier le temps absolu pour cela.
Comment puis-je implémenter cela dans Unix?
S'en tenir à pthread_cond_timedwait
et utilise clock_gettime
. Par exemple:
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 10; // ten seconds
while (!some_condition && ret == 0)
ret = pthread_cond_timedwait(&cond, &mutex, &ts);
Enveloppez-le dans une fonction si vous le souhaitez.
MISE À JOUR: complétant la réponse sur la base de nos commentaires.
POSIX n'a pas une seule API pour attendre "tous les types" d'événements/objets comme le fait Windows. Chacun a ses propres fonctions. La façon la plus simple de notifier un thread pour la terminaison est d'utiliser des variables/opérations atomiques. Par exemple:
Fil principal:
// Declare it globally (argh!) or pass by argument when the thread is created
atomic_t must_terminate = ATOMIC_INIT(0);
// "Signal" termination by changing the initial value
atomic_inc(&must_terminate);
Fil secondaire:
// While it holds the default value
while (atomic_read(&must_terminate) == 0) {
// Keep it running...
}
// Do proper cleanup, if needed
// Call pthread_exit() providing the exit status
Une autre alternative consiste à envoyer une demande d'annulation à l'aide de pthread_cancel
. Le thread en cours d'annulation doit avoir appelé pthread_cleanup_Push
pour enregistrer tout gestionnaire de nettoyage nécessaire. Ces gestionnaires sont appelés dans l'ordre inverse de leur enregistrement. N'appelez jamais pthread_exit
à partir d'un gestionnaire de nettoyage, car il s'agit d'un comportement non défini. Le statut de sortie d'un thread annulé est PTHREAD_CANCELED
. Si vous optez pour cette alternative, je vous recommande de lire principalement sur les points et types d'annulation.
Et enfin et surtout, appeler pthread_join
fera le bloc de thread actuel jusqu'à ce que le thread passé par l'argument se termine. En bonus, vous obtiendrez le statut de sortie du thread.
Pour ce que ça vaut, nous (NeoSmart Technologies) venons de publier une bibliothèque open source (sous licence MIT) appelée pevents qui implémente les événements manuels et de réinitialisation automatique WIN32 sur POSIX, et inclut les clones WaitForSingleObject et WaitForMultipleObjects.
Bien que je vous conseille personnellement d'utiliser les paradigmes de multithreading et de signalisation POSIX lors du codage sur les machines POSIX, pevents vous donne un autre choix si vous en avez besoin.
Je me rends compte que c'est une vieille question maintenant, mais pour toute personne qui tombe dessus, cette source suggère que pthread_join () fait effectivement la même chose que WaitForSingleObject ():
http://www.ibm.com/developerworks/linux/library/l-ipc2lin1/index.html
Bonne chance!
Pour WaitForMultipleObjects
avec false WaitAll
essayez ceci:
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
using namespace std;
pthread_cond_t condition;
pthread_mutex_t signalMutex;
pthread_mutex_t eventMutex;
int finishedTask = -1;
void* task(void *data)
{
int num = *(int*)data;
// Do some
sleep(9-num);
// Task finished
pthread_mutex_lock(&eventMutex); // lock until the event will be processed by main thread
pthread_mutex_lock(&signalMutex); // lock condition mutex
finishedTask = num; // memorize task number
pthread_cond_signal(&condition);
pthread_mutex_unlock(&signalMutex); // unlock condtion mutex
}
int main(int argc, char *argv[])
{
pthread_t thread[10];
pthread_cond_init(&condition, NULL);
pthread_mutex_init(&signalMutex, NULL); // First mutex locks signal
pthread_mutex_init(&eventMutex, NULL); // Second mutex locks event processing
int numbers[10];
for (int i = 0; i < 10; i++) {
numbers[i] = i;
printf("created %d\n", i); // Creating 10 asynchronous tasks
pthread_create(&thread[i], NULL, task, &numbers[i]);
}
for (int i = 0; i < 10;)
{
if (finishedTask >= 0) {
printf("Task %d finished\n", finishedTask); // handle event
finishedTask = -1; // reset event variable
i++;
pthread_mutex_unlock(&eventMutex); // unlock event mutex after handling
} else {
pthread_cond_wait(&condition, &signalMutex); // waiting for event
}
}
return 0;
}