Randy Martin a écrit :
i usually look at message_attach() and pulse_attach() for doing things outside
of the normal dispatch interface.
those are nice convenience callback functions that eliminate most of the
setup overhead… and still give me a multithreaded resmgr.
Igor Kovalenko <> Igor.Kovalenko@motorola.com> > wrote:
Mitchell Schoenbrun wrote:
Thanks for all the moral support guys. The theoretical
just got a little tragic last night. Here is what I
ran into.
I want to do something that I can write in my sleep in QNX4.
I have a manager that receives user messages but needs to
wake up occaisionally on its own. Under QNX4 I create a
proxy and attach it to a timer. The timer fires, triggers
the proxy and my Receive() wakes up.
You don’t really need pulse. Signals in Neutrino can carry data just
like pulses (they are implemented by same kernel object). They are also
more lightweight (tax your system less) and generally should be
preferred to pulses unless you have a good reason to do otherwise.
Now under Neutrino the fun starts. I’ll start with the
timer. I setup a timer to send a pulse periodically. One of
the first things I have to do is give the event structure a
connection id (coid). Ok, that’s fair, the timer needs to
know what connection to send the pulse over.
But now I have a catch 22. I could use ConnectCreate() to
create a channel, and then ConnectAttach() to create the coid.
But now I have a coid which cannot be found out by my clients.
Ok, back to the drawing board, I do a resmgr_attach(), but
where’s the channel id? It’s buried inside resmgr_attach().
Is it in the dispatch_t structure, probably, but I can’t find
this defined anywhere in /usr/include/*.
Hmm. I’d try to use name_attach() and name_locate() myself to get coid.
Perhaps name_locate() can locate a name attached by resmgr_attach() too,
who knows…
Might work, although I did not try it. Indeed, you can’t use open() for
that without help of another thread.
If resmgr_block() could wait on two coid’s then things would
be ok. Well it could do this by using select() I think, but
it doesn’t. I could write this code myself, but again I don’t
have the channel id to wait on for the client messages.
I did that using ionotify(), with similar scenario. Had a program
waiting on both timer and incoming data on a socket in a single event
loop. The timer handler then sent data to that socket (it was sort of
benchmark).
Maybe what I need to do is create a thread, have the thread
open the name space, and then have the timer send the pulse
to that way. It seems awful kludgy to need an extra thread
just to have a pulse wakeup a manager.
I hope I’ve missed something simple here. Can someone help
me out.
Yes it is kludgy as a way to obtain coid, but then using pulse to get
timer events is unnecessary overhead in the first place, if your timer
handler is very simple. Otherwise you might as well think and conclude
that having a separate thread might not be such a bad idea. You can’t
handle incoming messages while you’re handling timer and vice versa. If
your program gets to run on SMP then thread would be good. In any case
you might get better determinism under heavy load with separate thread.
–
Randy Martin > randy@qnx.com
Manager of FAE Group, North America
QNX Software Systems > www.qnx.com
175 Terence Matthews Crescent, Kanata, Ontario, Canada K2M 1W8
Tel: 613-591-0931 Fax: 613-591-3579
Of course Randy, After so many answers without this one, I was beginning to think
that I didn’t understand the subject. But what Michael want to do is really simple
like that.
The pseudo code is something like
main()
{
dpp = dispatch_create();
// if you need a resource manager
iofunc_attr_init(&attr, S_IFREG | 0xxx, 0, 0);
iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs, _RESMGR_IO_NFUNCS,
&io_funcs);
io_funcs.read = your_read; // if a client is supposed to read() from you
io_funcs.write = your_write; // if a client is supposed to write to you
io_funcs.msg = your_msg; // if a client is supposed to MsgSend() to you
resmgr_attach(dpp, &resmgr_attr, attach_name, _FTYPE_ANY, 0, &connect_funcs,
&io_funcs, &attr);
// if you need a pulse say, triggered by a timer to your dispatch interface,
just write:
pulse_code = pulse_attach(dpp, MSG_FLAG_ALLOC_PULSE, 0, your_function, NULL);
// note the dpp parameter
coid = message_connect(dpp, MSG_FLAG_SIDE_CHANNEL);
SIGEV_PULSE_INIT(&event, coid, SIGEV_PULSE_PRIO_INHERIT, pulse_code, 0);
timer_create(CLOCK_REALTIME, &event, &timerID);
itime.it_value.tv_sec = 1;
itime.it_value.tv_nsec = 0;
itime.it_interval.tv_sec = 1;
itime.it_interval.tv_nsec = 0;
timer_settime(timerID, 0, &itime, NULL);
ctp = resmgr_context_alloc(dpp);
while(1)
{
resmgr_block(ctp);
resmgr_handler(ctp);
}
}