Создать обработчик пула потоков
#include <sys/iofunc.h>#include <sys/dispatch.h>thread_pool_t * thread_pool_create( thread_pool_attr_t *pool_attr,unsigned flags );
<sys/dispatch.h>
), которые влияют на то, что случится с потоком, создающим пул: libc
Функция thread_pool_create() создаёт дескриптор пула потоков. Этот дескриптор затем используется для запуска пула потоков в thread_pool_start(). При помощи функций пула потоков можно создавать и управлять пулом рабочих потоков.
Как это работает
Рабочий поток ведёт себя следующим образом:
Поток продолжат блокировать и обрабатывать события пока пул потоков не решит, что этот рабочий поток более не нужен. Когда рабочий поток завершается, пул освобождает выделенный контекст.
Пул потоков управляет этими рабочими потоками так, что есть определённое количество потоков в заблокированном состоянии. Таким образом, когда потоки переходят к выполнению работы в функции-обработчике, пул создаёт новые потоки, чтобы сохранить минимальное количество потоков в состоянии, когда они могут принять запросы от клиентов. Таким же образом, если требования пула потоков снижаются, то некоторые из заблокированных потоков завершаются.
Дескриптор пула потоков.
Если возникла ошибка функция возвращает NULL
, код ошибки записывается в errno.
Ниже приведён пример простого многопоточного менеджера ресурсов:
/* 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 системной библиотеки