loop while (Type XRequests are available)
extract Request
process request
end loop
return(NULL)
}
В модели равноправных потоков каждый поток отвечает за собственный входной поток данных. Входные данные могут быть выделены из базы данных, файла и т.п.
Использование модели конвейера
В модели конве йера поток входных данных обрабатывается поэтапно. На каждом этапе некоторая порция работы (часть входного потока данных) обрабатывается одним потоком выполнения, а затем передается для обработки следующему. Каждая порция входных данных переходит на очередной этап обработки до тех пор, пока не будет завершена вся обработка. Такой подход позволяет обрабатывать несколько входных потоков данных одновременно. Каждый поток выполнения отвечает за достижение пром ежуточного результата, делая его доступным для следующего этапа (т.е. следующего потока конвейера). Скелет программы реализации модели конвейера представлен в листинге 4.9.
// Листинг 4.9. Скелет программы реализации модели конвейера
//...
pthread_t Thread[N]
Queues[N]
// initial thread
{
place all input into stage1's queue
pthread_create(&(Thread[1]...stage1...);
pthread_create(&(Thread[2]...stage2...);
pthread_create(&(Thread[3]...stage3...);
//...
}
void *stageX(void *X)
{
loop
suspend until input unit is in queue
loop while XQueue is not empty
dequeue input unit
process input unit
enqueue input unit into next stage's queue
end loop
until done
return(NULL)
}
В листинге 4.9 объявляется N очередей для N этапов. Начальный поток помещает все порции входных потоков в очередь первого этапа, а затем создает все потоки, необходимые для выполнения всех этапов. Каждый этап содержит свой цикл событий. Поток выполнения находится в состоянии ожидания до тех пор, пока в его очереди не появится порция входных данных. Внутренний цикл продолжается до опустения соответствующей очереди. Порция входных данных извлекается из очереди, обрабатывается, а затем помещается в очередь следующего этапа обработки (следующего потока выполнения).
Использование модели «изготовитель-потребитель»
В модели «изготовитель-потребитель» поток- «изготовитель» готовит данные, «потребляемые» потоком-«потребителем» (причем таких потоков-«потребителей' может быть несколько). Данные хранятся в блоке памяти, разделяемом всеми потока, как изготовителем, так и потребителями. В листинге 4.10 представлен скелет программы реализации модели «изготовитель-потребитель» (эта модель также использовалась в программах 4.5, 4.6 и 4.7).
Листинг 4.10. Скелет программы реализации модели «изготовитель-потребитель»
pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER
pthread_t Thread[2]
Queue
// initial thread
{
pthread_create(&(Thread[1]...producer...);
pthread_create(&(Thread[2]...consumer...);
//...
}
void *producer(void *X)
{
loop
perform work
pthread_mutex_lock(&Mutex)
enqueue data
pthread_mutex_unlock(&Mutex)
signal consumer
//...
until done
}
void *consumer(void *X)
{
loop
suspend until signaled
loop while(Data Queue not empty)
pthread_mutex_lock(&Mutex)
dequeue data
pthread_mutex_unlock(&Mutex)
perform work
end loop