Réveiller des threads individuels au lieu d’attendre des pthreads

Je ne suis pas sûr que le titre reflète ce que je demande ici, mais c’est mieux que je puisse faire sans un titre très long. J’essaie d’implémenter un modèle de worker thread dans pthreads . Je veux créer un ensemble de threads à partir de la fonction main , puis le thread main délègue le travail au travailleur et attend que tous les threads soient terminés avant de leur atsortingbuer le travail suivant (en réalité, il est nécessaire de disposer le thread dans un bloc beaucoup comme le modèle de programmation CUDA mais sur la CPU, bien que ce ne soit pas pertinent pour la question actuelle). Le tableau de travaux est utilisé pour indiquer le type de travail à chaque thread. Actuellement, j’ai implémenté cela en utilisant des sémaphores qui imposent une attente occupée. Je cherche des moyens de faire en sorte que les threads ne s’endormissent et ne se réveillent que lorsqu’ils sont requirejs, au lieu d’interroger en continu.

La fonction exécutée par chaque thread

 volatile int jobs[MAX_THREADS]; // global job indicator array sem_t semaphore; // semaphore to indicate completion thread_execute(void *args) { tid = get_id(args); while(jobs[tid] != -1) { if(jobs[tid] == 0) continue; // no job if(jobs[tid] == JOBS_1) { jobs1(); jobs[tid] = 0; // go back to idle state sem_post(&semapahore); } if(jobs[tid] == JOBS_2) { jobs2(); jobs[tid] = 0; // go back to idle state sem_post(&semapahore); } } pthread_exit(NULL); } 

La fonction principale est la suivante

 int main() { sem_init(&semaphore, 0, 0); jobs[0...MAX_THREADS] = 0; spawn_threads(); // Dispatch first job jobs[0...MAX_THREADS] = JOBS_1; int semvalue = 0; while (semvalue < MAX_THREADS) // Wait till all threads increment the semaphore sem_getvalue(&sempaphore, &semvalue); sem_init(&semaphore, 0, 0); // Init semaphore back to 0 for the next job // I'm actually using diff. semaphores for diff. jobs jobs[0...MAX_THREADS] = JOBS_2; while (semvalue < MAX_THREADS) sem_getvalue(&sempaphore, &semvalue); jobs[0...MAX_THREADS] = -1; // No more jobs pthread_join(); } 

Le problème de cette implémentation est que le thread main est occupé à attendre que tous les threads de travail soient terminés et que les threads de travail interrogent également en permanence le tableau de travaux pour rechercher un nouveau travail. Y a-t-il une meilleure façon de faire cela quand les threads se mettent en sumil et se réveillent quand cela est nécessaire le long des lignes d’un gestionnaire de singal et en utilisant pthread_kill() mais c’est un peu compliqué avec un gestionnaire de signal séparé.

Vous pouvez utiliser une variable conditionnelle pour mettre les threads en veille jusqu’à ce qu’ils soient signalés.

 volatile int jobs[MAX_THREADS]; // global job indicator array pthread_cond_t th_cond; // threads wait on this pthread_mutex_t th_mutex; // mutex to protect the signal int busyThreads = MAX_THREADS; pthread_cond_t m_cond; // main thread waits on this pthread_mutex_t m_mutex; // mutex to protect main signal thread_execute(void *args) { tid = get_id(args); while(jobs[tid] != -1) { if(jobs[tid] == 0) continue; // no job if(jobs[tid] == JOBS_1) { jobs1(); jobs[tid] = 0; // go back to idle state pthread_mutex_lock(&th_mutex); pthread_mutex_lock(&m_mutex); --busyThreads; // one less worker pthread_cond_signal(&m_cond); // signal main to check progress pthread_mutex_unlock(&m_mutex); pthread_cond_wait(&th_cond, &th_mutex); // wait for next job pthread_mutex_unlock(&th_mutex); } if(jobs[tid] == JOBS_2) { jobs2(); jobs[tid] = 0; // go back to idle state pthread_mutex_lock(&th_mutex); --busyThreads; pthread_cond_wait(&th_cond, &th_mutex); pthread_mutex_unlock(&th_mutex); } } pthread_exit(NULL); } 

puis en principal:

 int main() { sem_init(&semaphore, 0, 0); jobs[0...MAX_THREADS] = 0; spawn_threads(); // Dispatch first job jobs[0...MAX_THREADS] = JOBS_1; int semvalue = 0; pthread_mutex_lock(&m_mutex); while(busyThreads > 0) // check number of active workers pthread_cond_wait(&m_cond, &m_mutex); pthread_mutex_unlock(&m_mutex); busyThreads = MAX_THREADS; pthread_mutex_lock(&th_mutex); pthread_cond_broadcast(&th_cond); // signal all workers to resume pthread_mutex_unlock(&th_mutex); // same for JOBS_2; jobs[0...MAX_THREADS] = -1; // No more jobs pthread_join(); }