/**
@page GRAS_tut_tour_callbacks Lesson 4: Attaching callbacks to messages
\section GRAS_tut_tour_callbacks_toc Table of Contents
- \ref GRAS_tut_tour_callbacks_declare
- \ref GRAS_tut_tour_callbacks_attach
- \ref GRAS_tut_tour_callbacks_handle
- \ref GRAS_tut_tour_callback_recap
Our program is well and good, but if we had to write a longer program,
explicitely waiting for messages of a given type would not be really
practical. To add some more dynamism, what we want to do is to attach
callbacks to the several messages types, and tell GRAS that we are ready to
deal with new messages. That's what we will do now.
\section GRAS_tut_tour_callbacks_declare Declaring callbacks
First of all, we define the callback we want to attach to the arrival of the
"hello" message on the server. Its signature is fixed: it accepts two
arguments of relative types gras_msg_cb_ctx_t ctx and void
*. The first one is a working context we should pass to GRAS when
speaking about the message we are handling while the second is the payload.
The callbackreturns an integer indicating whether we managed to deal with
the message. I admit that this semantic is a bit troublesome, it should be 0
if we managed to deal properly with the message to mimic "main()" semantic.
That's historical, but I may change this in the future (no worry, I'll add
backward compatibility solutions). Here is the actual code of our callback:
\dontinclude 04-callback.c
\skip gras_msg_cb_ctx_t
\until end_of_callback
\section GRAS_tut_tour_callbacks_attach Attaching callbacks
Then, we have to change the server code to use this callback instead of
gras_msg_wait. This simply done by a construct like the following:
\skip cb_register
\until cb_register
\section GRAS_tut_tour_callbacks_handle Handling incoming messages
Once the callback is declared and attached, the server simply has to call
\ref gras_msg_handle to tell GRAS it's ready to handle for incoming
messages. The only argument is the maximum delay we are disposed to wait for
a message. If the delay is negative, the process will block until a message
arrives. With delay=0, the process just polls for already arrived messages,
but do not wait at all if none arrived yet. If the delay is greater than 0,
the process will wait for at most that amount of seconds. If a message
arrives in the meanwhile, it won't even wait that long.
Sometimes, you want to handle all messages arriving in a given period
without really knowing how much messages will come (this is often the case
during the initialization phase of an algorithm). In that case, use \ref
gras_msg_handleall . It has the same prototype than \ref gras_msg_handle,
but waits exactly the passed delay, dealing with all the messages arriving
in the meanwhile.
We have no such needs in our example, so the code simply reads:
\skip handle
\until handle
\section GRAS_tut_tour_callback_recap Recaping everything together
The whole program now reads:
\include 04-callback.c
And here is the output (unchanged wrt previous version):
\include 04-callback.output
Our little example turns slowly to a quite advanced GRAS program. It entails
most of the mecanism most program will use.
There is one last thing you should know about callbacks: you can stack them,
ie attach several callbacks to the same message. GRAS will pass it to the
lastly attached first, and if the return value is 0, it will pass it also to
the next one, and so on. I'm not sure there is any sensible use of this
feature, but it's possible ;)
Go to \ref GRAS_tut_tour_globals
*/