Blocking within the resource manager

So far we've avoided talking about blocking within the resource manager. We assume that you will supply an outcall function (e.g., a handler for io_read()), and that the data will be available immediately. What if you need to block, waiting for the data? For example, performing a read() on the serial port might need to block until a character arrives. Obviously, we can't predict how long this will take.

Blocking within a resource manager is based on the same principles that we discussed in the Message Passing chapter—after all, a resource manager is really a server that handles certain, well-defined messages. When the message corresponding to the client's read() request arrives, it does so with a receive ID, and the client is blocked. If the resource manager has the data available, it will simply return the data as we've already seen in the various examples above. However, if the data isn't available, the resource manager will need to keep the client blocked (if the client has indeed specified blocking behavior for the operation) to continue processing other messages. What this really means is that the thread (in the resource manager) that received the message from the client should not block, waiting for the data. If it did block, you can imagine that this could eventually use up a great number of threads in the resource manager, with each thread waiting for some data from some device.

The correct solution to this is to store the receive ID that arrived with the client's message onto a queue somewhere, and return the special constant _RESMGR_NOREPLY from your handler. This tells the resource manager library that processing for this message has completed, but that the client shouldn't be unblocked yet.

Some time later, when the data arrives, you would then retrieve the receive ID of the client that was waiting for the message, and construct a reply message containing the data. Finally, you would reply to the client.

You could also extend this concept to implementing timeouts within the server, much as we did with the example in the Clocks, Timers, and Getting a Kick Every So Often chapter (in the “Server-maintained timeouts” section). To summarize, after some period of time, the client's request was deemed to have “timed out” and the server replied with some form of failure message to the receive ID it had stored away.