thread_pool_create()

Создать обработчик пула потоков

Прототип:

#include <sys/iofunc.h>
#include <sys/dispatch.h>
thread_pool_t * thread_pool_create( thread_pool_attr_t *pool_attr,
unsigned flags );

Аргументы:

pool_attr
Указатель на структуру thread_pool_attr_t, определяющую атрибуты пула потоков.
flags
Флаги (определённые в <sys/dispatch.h>), которые влияют на то, что случится с потоком, создающим пул:
POOL_FLAG_EXIT_SELF
когда пул начинает работу при помощи thread_pool_start(), поток, вызвавший эту функцию, завершается.
POOL_FLAG_USE_SELF
когда пул начинает работу, вызывающий поток используется, как часть пула.

Библиотека:

libc

Описание:

Функция thread_pool_create() создаёт дескриптор пула потоков. Этот дескриптор затем используется для запуска пула потоков в thread_pool_start(). При помощи функций пула потоков можно создавать и управлять пулом рабочих потоков.

Как это работает

Рабочий поток ведёт себя следующим образом:

Поток продолжат блокировать и обрабатывать события пока пул потоков не решит, что этот рабочий поток более не нужен. Когда рабочий поток завершается, пул освобождает выделенный контекст.

Пул потоков управляет этими рабочими потоками так, что есть определённое количество потоков в заблокированном состоянии. Таким образом, когда потоки переходят к выполнению работы в функции-обработчике, пул создаёт новые потоки, чтобы сохранить минимальное количество потоков в состоянии, когда они могут принять запросы от клиентов. Таким же образом, если требования пула потоков снижаются, то некоторые из заблокированных потоков завершаются.

Возвращаемое значение:

Дескриптор пула потоков.

Если возникла ошибка функция возвращает NULL, код ошибки записывается в errno.

Коды ошибок:

ENOMEM
Недостаточно памяти для выделения внутренних структур.

Примеры:

Ниже приведён пример простого многопоточного менеджера ресурсов:

/* Define an appropriate interrupt number: */
#define INTNUM 0
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <sys/neutrino.h>
static resmgr_connect_funcs_t connect_funcs;
static resmgr_io_funcs_t io_funcs;
static iofunc_attr_t attr;
void * interrupt_thread( void *data ) /* *data isn't used */
{
struct sigevent event;
int id;
/* fill in "event" structure */
memset( &event, 0, sizeof( event ) );
event.sigev_notify = SIGEV_INTR;
/* INTNUM is the desired interrupt level */
id = InterruptAttachEvent( INTNUM, &event, 0 );
...
while ( 1 )
{
InterruptWait( 0, NULL );
/*
* do something about the interrupt, perhaps updating some shared
* structures in the resource manager
*
* unmask the interrupt when done
*/
InterruptUnmask( INTNUM, id );
}
}
int main( int argc, char **argv )
{
thread_pool_attr_t pool_attr;
thread_pool_t *tpp;
dispatch_t *dpp;
resmgr_attr_t resmgr_attr;
int id;
if ( (dpp = dispatch_create()) == NULL )
{
fprintf( stderr, "%s: Unable to allocate dispatch handle.\n", argv[0] );
return (EXIT_FAILURE);
}
memset( &pool_attr, 0, sizeof pool_attr );
pool_attr.handle = dpp;
pool_attr.context_alloc = dispatch_context_alloc;
pool_attr.block_func = dispatch_block;
pool_attr.unblock_func = dispatch_unblock;
pool_attr.handler_func = dispatch_handler;
pool_attr.context_free = dispatch_context_free;
pool_attr.lo_water = 2;
pool_attr.hi_water = 4;
pool_attr.increment = 1;
pool_attr.maximum = 50;
pool_attr.tid_name = "my_thread_pool";
if ( (tpp = thread_pool_create( &pool_attr, POOL_FLAG_EXIT_SELF )) == NULL )
{
fprintf( stderr, "%s: Unable to initialize thread pool.\n", argv[0] );
return (EXIT_FAILURE);
}
iofunc_func_init( _RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs );
iofunc_attr_init( &attr, S_IFNAM | 0666, 0, 0 );
memset( &resmgr_attr, 0, sizeof resmgr_attr );
resmgr_attr.nparts_max = 1;
resmgr_attr.msg_max_size = 2048;
if ( (id = resmgr_attach( dpp, &resmgr_attr, "/dev/mynull", _FTYPE_ANY, 0,
&connect_funcs, &io_funcs, &attr )) == -1 )
{
fprintf( stderr, "%s: Unable to attach name.\n", argv[0] );
return (EXIT_FAILURE);
}
/* Start the thread which will handle interrupt events. */
pthread_create( NULL, NULL, interrupt_thread, NULL );
/* Never returns */
thread_pool_start( tpp );
}

Другие примеры, использующие интерфейс диспетчера см. на страницах dispatch_create(), message_attach() и resmgr_attach().

Классификация:

ЗОСРВ «Нейтрино»

Безопасность использования
Точка остановки потока
Нет
Обработчик прерываний
Нет
Обработчик сигналов
Нет
В потоке
Да

Тематические ссылки:

thread_pool_attr_t, dispatch_block(), dispatch_create(), dispatch_unblock(), pthread_create(), resmgr_attach(), select_attach(), thread_pool_destroy(), thread_pool_start()




Предыдущий раздел: Описание API системной библиотеки