message_attach()

Определить диапазон сообщений для обработчика

Прототип:

#include <sys/iofunc.h>
#include <sys/dispatch.h>
int message_attach( dispatch_t *dpp,
message_attr_t *attr,
int low,
int high,
int (*func)( message_context_t *ctp,
int code,
unsigned flags,
void *handle ),
void *handle );

Аргументы:

dpp
Дескриптор диспетчера, возвращаемый функцией dispatch_create().
attr
Указатель на структуру message_attr_t, которая устанавливает дополнительные требования к сообщению.
low
high
Диапазон интересующих сообщений.

Note: Несмотря на то, что эти аргументы имеют тип int, message_attach() сохраняет их значения внутри как short.

func
Функция, которая будет вызвана при получении сообщения из указанного диапазона: смотрите “Функция обработчик” ниже.
handle
Произвольный дескриптор, который будет ассоциироваться с данными для указанного диапазона сообщений. Этот дескриптор передаётся в func.

Библиотека:

libc

Описание:

Функция message_attach() подключает обработчик для диапазона сообщений [low, high] (включая сообщения на границах диапазона) для дескриптора диспетчера dpp.


Note: Использование перекрывающихся диапазонов сообщений или пульсов считается ошибкой написания кода. Типы сообщений должны быть больше значения _IO_MAX (определена в <sys/iomsg.h>).

При получении сообщения с типом, принадлежащим указанному диапазону, dispatch_handler() вызывает установленную пользователем функцию-обработчик func. Также можно использовать ту же функцию с pulse_attach(). Изучая ctp->rcvid в func можно определить, получен пульс или сообщение.

Эта функция отвечает за выполнение любой работы, необходимой для обработки сообщения, находящегося в ctp->msg. Дескриптор handle, переданный в функцию-обработчик, это дескриптор handle, изначально переданный в message_attach().

Функция обработчик

Пользовательская функция func вызывается при получении сообщения из заданного диапазона. Функция получает контекст сообщения ctp, в котором находится сообщение, тип сообщения, и дескриптор handle (переданный в message_attach()). В настоящее время аргумент flags зарезервирован. Пользовательская функция должна возвращать 0; другие возвраты зарезервированы.

Контекст сообщения соответствует описанию структуры message_context_t.

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

0
Успешное завершение.
-1
Возникла ошибка. Код ошибки записан в errno.

Коды ошибок:

EINVAL
Код сообщения code вне допустимого диапазона.
ENOMEM
Недостаточно памяти для подключения обработчика сообщений данного типа.

Примеры:

В данном примере создаётся менеджер ресурсов, в котором происходит подключение обработчика для диапазона приватных сообщений и пульса, который будет использован для события таймера:

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define THREAD_POOL_PARAM_T dispatch_context_t
#include <sys/iofunc.h>
#include <sys/dispatch.h>
static resmgr_connect_funcs_t connect_func;
static resmgr_io_funcs_t io_func;
static iofunc_attr_t attr;
int timer_tick( message_context_t *ctp, int code, unsigned flags, void *handle )
{
union sigval value = ctp->msg->pulse.value;
/* Do some useful work on every timer firing... */
printf( "received timer event, value %d\n", value.sival_int );
return (0);
}
int message_handler( message_context_t *ctp, int code, unsigned flags, void *handle )
{
printf( "received private message, type %d\n", code );
return (0);
}
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;
int timer_id;
struct sigevent event;
struct _itimer itime;
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;
/* We are doing resmgr and pulse-type attaches */
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;
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_func,
_RESMGR_IO_NFUNCS, &io_func );
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_func, &io_func, &attr )) == -1 )
{
fprintf( stderr, "%s: Unable to attach name.\n", argv[0] );
return (EXIT_FAILURE);
}
/* We want to handle our own private messages, of type 0x5000 to 0x5fff */
if ( message_attach( dpp, NULL, 0x5000, 0x5fff, &message_handler, NULL ) == -1 )
{
fprintf( stderr, "Unable to attach to private message range.\n" );
return (EXIT_FAILURE);
}
/* Initialize an event structure and attach a pulse to it */
if ( (event.sigev_code = pulse_attach( dpp, MSG_FLAG_ALLOC_PULSE, 0, &timer_tick, NULL )) == -1 )
{
fprintf( stderr, "Unable to attach timer pulse.\n" );
return (EXIT_FAILURE);
}
/* Connect to our channel */
if ( (event.sigev_coid = message_connect( dpp, MSG_FLAG_SIDE_CHANNEL )) == -1 )
{
fprintf( stderr, "Unable to attach to channel.\n" );
return (EXIT_FAILURE);
}
event.sigev_notify = SIGEV_PULSE;
event.sigev_priority = -1;
/* We could create several timers and use different sigev values for each */
event.sigev_value.sival_int = 0;
if ( (timer_id = TimerCreate( CLOCK_REALTIME, &event )) == -1 )
{
fprintf( stderr, "Unable to attach channel and connection.\n" );
return (EXIT_FAILURE);
}
/* And now setup our timer to fire every second */
itime.nsec = 1000000000;
itime.interval_nsec = 1000000000;
TimerSettime( timer_id, 0, &itime, NULL );
/* Never returns */
thread_pool_start( tpp );
return (EXIT_SUCCESS);
}

Для примера использования интерфейса диспетчера см. dispatch_create(), resmgr_attach(), и thread_pool_create().

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

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

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

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

message_attr_t, message_context_t, dispatch_block(), dispatch_create(), dispatch_handler(), dispatch_unblock(), message_connect(), message_detach(), struct _msg_info, pulse_attach()




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