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
The dispatch handle, as returned by dispatch_create().
attr
A pointer to a message_attr_t structure that lets you specify additional requirements for the message.
low
high
The range of messages that you're interested in.

Note: Although these arguments are of type int, message_attach() stores the values internally as short.

func
The function that you want to call when a message in the given range is received; see “Handler function” below.
handle
An arbitrary handle that you want to associate with data for the defined message range. This handle is passed to func.

Библиотека:

libc

Описание:

The message_attach() function attaches a handler to the message range defined by the message type [low, high] (i.e. an inclusive message range) for dispatch handle dpp.


Note: It's considered a programming error to attach overlapping message or pulse ranges. Message types should be greater than _IO_MAX (defined in <sys/iomsg.h>.

When a message with a type in that range is received, dispatch_handler() calls the user-supplied function func. You can also use the same function with pulse_attach(). By examining ctp->rcvid, func can determine whether a pulse or message was received.

This function is responsible for doing any specific work needed to handle the message pointed to by ctp->msg. The handle passed to the function is the handle initially passed to message_attach().

Handler function

The user-supplied function func is called when a message in the defined range is received. This function is passed the message context ctp, in which the message was received, the message type, and the handle (the one passed to message_attach()). Currently, the argument flags is reserved. Your function should return 0; other return values are reserved.

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

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

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

Коды ошибок:

EINVAL
The message code is out of range.
ENOMEM
Insufficient memory to attach message type.

Примеры:

In this example, we create a resource manager where we attach to a private message range and attach a pulse, which is then used as a timer event:

#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);
}

For more examples using the dispatch interface, see dispatch_create(), resmgr_attach(), and 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 системной библиотеки