Я не уверен, отражает ли заголовок то, что я здесь спрашиваю, но это лучшее, что я могу сделать без очень длинного заголовка.Я пытаюсь реализовать модель worker thread
в pthreads
.Я хочу порождать набор потоков из функции main
, и после этого поток main
делегирует задание работнику и ожидает завершения всех потоков, прежде чем назначить им следующее задание (На самом деле, требуется организовать потокв блоке, очень похожем на модель программирования CUDA, но на CPU. Хотя это не относится к текущему вопросу).Массив job
используется для указания типа задания для каждого потока.В настоящее время я реализовал это с помощью семафоров, что требует напряженного ожидания.Я ищу способы сделать так, чтобы потоки переходили в спящий режим и просыпались только тогда, когда они необходимы, а не опрашивали непрерывно.
Функция, выполняемая каждым потоком
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);
}
Основная функция выглядит следующим образом:
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();
}
Проблема этой реализации состоит в том, что поток main
занят, ожидая завершения всех рабочих потоков, и рабочие потоки также постоянно опрашивают массив заданий, чтобы проверить наличиеновая работа.Есть ли лучший способ сделать это, когда потоки засыпают и просыпаются, когда это необходимо, по аналогии с обработчиком сингалов и использованием pthread_kill()
, но это немного запутанно с отдельным обработчиком сигналов.