The MsgReceivePulse() function
The MsgReceive() and MsgReceivev() functions will
receive either a regular
message or a pulse.
There may be situations where you want to receive only pulses.
The best example of this is in a server where you've received a request from a client
to do something, but can't complete the request just yet (perhaps you have to do
a long hardware operation).
In such a design, you'd generally set up the hardware (or a timer, or whatever) to send
you a pulse whenever a significant event occurs.
If you write your server using the classic wait in an infinite loop for messages
design, you might run into a situation where one client sends you a request,
and then, while you're waiting for the pulse to come in (to signal completion of the request),
another client sends you another request.
Generally, this is exactly what you want—after all, you want
to be able to service multiple clients at the same time.
However, there might be good reasons why this is not acceptable—servicing a client
might be so resource-intensive that you want to limit the number of clients.
selectivelyreceive only a pulse, and not a regular message. This is where MsgReceivePulse() comes into play:
#include <sys/neutrino.h>
int MsgReceivePulse (int chid,
void *rmsg,
size_t rbytes,
struct _msg_info *info);
As you can see, you use the same parameters as MsgReceive(); the channel
ID, the buffer (and its size), as well as the info parameter.
(We discussed the info parameter above, in Who sent the message?
.)
Note that the info parameter is not used in the case of a pulse; you might ask why
it's present in the parameter list.
Simple answer: it was easier to do it that
way in the implementation. Just pass a NULL!
The MsgReceivePulse() function will receive nothing but pulses. So, if you had a channel with a number of threads blocked on it via MsgReceivePulse() (and no threads blocked on it via MsgReceive()), and a client attempted to send your server a message, the client would remain SEND-blocked until a thread issued the MsgReceive() call. Pulses would be transferred via the MsgReceivePulse() functions in the meantime.
The only thing you can guarantee if you mix both MsgReceivePulse() and MsgReceive() is that the MsgReceivePulse() will get pulses only. The MsgReceive() could get pulses or messages! This is because, generally, the use of the MsgReceivePulse() function is reserved for the cases where you want to exclude regular message delivery to the server.
This does introduce a bit of confusion. Since the MsgReceive() function can receive both a message and a pulse, but the MsgReceivePulse() function can receive only a pulse, how do you deal with a server that makes use of both functions?
Generally, the answer here is that you'd have a pool of threads that are performing
MsgReceive().
This pool of threads (one or more threads; the number depends on how many clients you're prepared
to service concurrently) is responsible for handling client calls (requests for service).
Since you're trying to control the number of service-providing threads,
and since some of these threads may need to block, waiting for a pulse to arrive (for example,
from some hardware or from another thread), you'd typically block the service-providing thread
using MsgReceivePulse().
This ensures that a client request won't sneak in
while you're waiting for
the pulse (since MsgReceivePulse() will receive only a pulse).