Start the resource manager message loop

/* start the resource manager message loop */
while(1) {
    if((ctp = dispatch_block(ctp)) == NULL) {
        fprintf(stderr, "block error\n");
        return EXIT_FAILURE;
    }
    dispatch_handler(ctp);
}

Once the resource manager establishes its name, it receives messages when any client program tries to perform an operation (e.g., open(), read(), write()) on that name.

In our example, once /dev/sample is registered, and a client program executes:

fd = open ("/dev/sample", O_RDONLY);

the client's C library constructs an _IO_CONNECT message and sends it to our resource manager. Our resource manager receives the message within the dispatch_block() function. We then call dispatch_handler(), which decodes the message and calls the appropriate handler function based on the connect and I/O function tables that we passed in previously. After dispatch_handler() returns, we go back to the dispatch_block() function to wait for another message.

Note:
Note that dispatch_block() returns a pointer to a dispatch context (dispatch_context_t) structure—the same type of pointer you pass to the routine:
  • If dispatch_block() returns a non-NULL context pointer, it could be different from the one passed in, as it's possible for the ctp to be reallocated to a larger size. In this case, the old ctp is no longer valid.
  • If dispatch_block() returns NULL (for example, because a signal interrupted the MsgReceive()), the old context pointer is still valid. Typically, a resource manager targets any signals to a thread that's dedicated to handling signals. However, if a signal can be targeted to the thread doing dispatch_block(), you could use the following code:
    dispatch_context_t   *ctp, *new_ctp;
    
    ctp = dispatch_context_alloc( … );
    while (1) {
       new_ctp = dispatch_block( ctp );
       if ( new_ctp ) {
          ctp = new_ctp
          }
       else {
          /* handle the error condition */
          …
          }
    }
    

At some later time, when the client program executes:

read (fd, buf, BUFSIZ);

the client's C library constructs an _IO_READ message, which is then sent directly to our resource manager, and the decoding cycle repeats.

Page updated: