IM-324: Persistent/non-persistent and single/multiple notify callbacks

From: Per Bojsen <per.bojsen@amd.com>
Date: Wed Mar 03 2010 - 08:46:29 PST

Hi,

in the following I'm using persistent in place of sticky and one-time
instead of non-sticky with respect to how notify callbacks are handled.
Sticky/non-sticky sounds a little too much like cute jargon to me :-)

the spec. currently supports (up to) one persistent callback per pipe
instance. The callback is _persistent_ in that it is not automatically
deregistered when called by the infrastructure. This is consistent with
other callbacks defined in SCE-MI. The callbacks defined in the
macro-based interface include:

   1) Output port receive callbacks
   2) Output port close callbacks
   3) Service loop handler
   4) Error handler
   5) Warning handler

All of these are persistent.

As a user, I find the one-time callback semantics way less useful
than the persistent semantics. I believe Russ also agreed with me on
that. The canonical implementation of the blocking pipe API on top of
the non-blocking API is also simplified by using persistent semantics
since the same notify callback need to remain in place throughout the
run.

A comment in the Word document that goes with IM-324 uses UNIX signal
handlers as an example of one-time callback semantics. Even there,
though, the trend has moved towards persistent callbacks. See for
example the sigaction() POSIX function. I suspect that part of the
reason the UNIX signal handlers used to be one-time was to protect
against recursion in the signal handler if the signal was received
again while being received. But that is not an issue for our notify
callbacks. We know that we cannot receive another notify action while
the notify callback is executing.

The problem with the one-time callback semantics is that the user is
now forced to reregister his callback every time it is called. So
there is a price to be payed: The overhead from the infrastructure of
removing the callback and the overhead in the user's callback of
registering the callback again. This is bad since that is going to
be the common case in my opinion.

It has been argued before that one-time callback behavior can be
achieved by having the callback deregister itself. This is a lesser
penalty to have to pay than the opposite case I described above.
Since one-time callbacks presumably are going to be called less
often (otherwise, why make them one-time?), that reduces the penalty
even further when summed over the simulation time.

If there is still insistence on adding support for the one-time
callback semantics, then at least make it up to the user to choose
between persistent and one-time semantics. For instance,

void scemi_pipe_set_notify_callback(
     void *pipe_handle, // input: pipe handle
     scemi_pipe_notify_callback notify_callback,
                             // input: notify callback function
     void *notify_context, // input: notify context
     bool one_time ); // input: if true request one-time semantics

The new boolean argument one_time chooses betwween one-time (true)
and persistent (false) semantics. This is very easy to implement
in the infrastrucure and requires only a few lines of code.

The other issue raised in IM-324 is whether to allow multiple notifty
callbacks to be registered for each pipe. I don't have a strong
opinion either way on this, but I do see some issues that need to
be resolved if we allow multiple callbacks:

   1) Specify the order in which multiple callbacks are invoked.
      One possibility is to leave it unspecified, i.e.., to say
      that any code that relies on the order will produce unpredictable
      results. The other reasonable possibility is to use the
      order of registration.

   2) Specify how to deregister a callback. Currently, since we
      allow only one callback to be registered, we have declared that
      passing NULL will deregister the callback. Or you can pass
      another callback pointer and the old one will be deregistered
      while the new one is registered. With multiple callbacks
      there needs to exist a way to state which callback you are
      deregistering. This probably requires a new function to avoid
      confusion. One way is to have scemi_pipe_set_notify_callback()
      return a unique ID that identifies the pipe_handle/callback/notify context
      combination. Then to deregister you pass the ID to the
      new deregister function.

Of course, all of the above can be implemented by the user if desired
within the current single callback framework. The question is whether
the added complexity in the standard is warranted given that this
feature is going to be relatively rarely used. One compromise solution
would be to add an appendix with some code examples that show how to
do this. The vendor could then include this code in an SCE-MI application
library the user could take advantage of.

Lastly, I want to reiterate what I'm pretty sure has come up before:
The scemi_pipe_set_notify_callback() function needs to have a return
type of scemi_pipe_notify_callback and return the current registered
notify callback if we stick with the single callback semantics. Note,
that is not quite satisfactory as you also need the notify context
pointer to be able to do proper chaining.

To get around the last problem we could follow the pattern of sigaction()
and use a struct:

   struct scemi_pipe_notify_callback
   {
     void (*cb)(void *);
     void *context;
   };

Then use the following definition for the register function:

scemi_pipe_notify_callback *scemi_pipe_set_notify_callback(
     void *pipe_handle, // input: pipe handle
     scemi_pipe_notify_callback *notify_callback,
                        // input: notify callback function and context
     bool one_time ); // input: if true request one-time semantics

We should require the implementation to copy the contents of the
callback struct so that the user is free to reuse or deallocate it.
That is important because otherwise the user would not be able to
use scemi_pipe_notify_callback objects that are local to a function
which could lead to hard to debug problems. Similarly, the return
value should be guaranteed only until the next SCE-MI API call or
something like that so the user would be required to extract the
info ASAP. In practice, that is not a big deal.

Thanks,
Per

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Wed Mar 3 08:47:39 2010

This archive was generated by hypermail 2.1.8 : Wed Mar 03 2010 - 08:47:45 PST