How do you receive a timeout notification? With the delay timer, you received notification by virtue of being made READY again. With periodic and one-shot timers, you have a choice:
We've talked about pulses in Message passing, signals are a standard UNIX-style mechanism, and we'll talk about the thread creation notification type shortly.
Let's take a quick look at how you fill in the struct sigevent structure. Regardless of the notification scheme you choose, you need to fill in a struct sigevent structure:
struct sigevent {
int sigev_notify;
union {
int sigev_signo;
int sigev_coid;
int sigev_id;
void (*sigev_notify_function) (union sigval);
};
union sigval sigev_value;
union {
struct {
short sigev_code;
short sigev_priority;
};
pthread_attr_t *sigev_notify_attributes;
};
};
The first field you have to fill in is the sigev_notify member. This determines the notification type you've selected:
Since we are using the struct sigevent with timers, we're concerned only with the SIGEV_PULSE, SIGEV_SIGNAL* and SIGEV_THREAD values for sigev_notify; we see the other types as mentioned in the list above.
To send a pulse when the timer fires, set the sigev_notify field to SIGEV_PULSE and provide some extra information:
| Field | Value and meaning |
|---|---|
| sigev_coid | Send the pulse to the channel associated with this connection ID. |
| sigev_value | A 32-bit value that gets sent to the connection identified in the sigev_coid field. |
| sigev_code | An 8-bit value that gets sent to the connection identified in the sigev_coid field. |
| sigev_priority | The pulse's delivery priority. The value zero is not allowed (too many people were getting caught by running at priority zero when they got a pulse — priority zero is what the idle task runs at, so effectively they were competing with BlackBerry 10 OS's IDLE process and not getting much CPU time). |
Note that the sigev_coid could be a connection to any channel (usually, though not necessarily, the channel associated with the process that's initiating the event).
To send a signal, set the sigev_notify field to one of:
For SIGEV_SIGNAL*, the additional fields you have to fill are:
| Field | Value and meaning |
|---|---|
| sigev_signo | Signal number to send (from <signal.h>, for example, SIGALRM). |
| sigev_code | An 8-bit code (if using SIGEV_SIGNAL_CODE or SIGEV_SIGNAL_THREAD). |
To create a thread whenever the timer fires, set the sigev_notify field to SIGEV_THREAD and fill these fields:
| Field | Value and meaning |
|---|---|
| sigev_notify_function | Address of void * function that accepts a void * to be called when the event triggers. |
| sigev_value | Value passed as the parameter to the sigev_notify_function() function. |
| sigev_notify_attributes | Thread attributes structure (see The thread attributes structure for details). |
There are some convenience macros in <sys/siginfo.h> to make filling in the notification structures easier (see the entry for sigevent in the BlackBerry 10 OS C Library Reference):
Suppose you're designing a server that spent most of its life RECEIVE blocked, waiting for a message. Wouldn't it be ideal to receive a special message, one that told you that the time you had been waiting for finally arrived? This scenario is exactly where you should use pulses as the notification scheme. In Using timers , there is some sample code that can be used to get periodic pulse messages.
Suppose that, you're performing some kind of work, but don't want that work to go on forever. For example, you may be waiting for some function call to return, but you can't predict how long it takes. In this case, using a signal as the notification scheme, with perhaps a signal handler, is a good choice (another choice we'll discuss later is to use kernel timeouts; see _NTO_CHF_UNBLOCK . In Using timers, we'll see a sample that uses signals.
Alternatively, a signal with sigwait() is cheaper than creating a channel to receive a pulse on, if you're not going to be receiving messages in your application anyway.