Rogue Wave banner
Previous fileTop of DocumentContentsIndexNext file

17.5 Treating the Receptionist as an Object

After reading the code we've just described you may be asking yourself "Where's the receptionist?" Good question. The code that belongs in the receptionist has been incorporated right into the body of the program. This works fine for this code because the program is so simple and because the receptionist doesn't deal with much state. For more complicated receptionists, though, this situation is not acceptable. In this section, we'll pull the receptionist code out of main() and create a sequential receptionist class.

17.5.1 Coordinating Receptionists and Workers: Callbacks

Usually, you use a C++ object by calling member functions on the object. The member function runs, and when it is finished control returns to you.

Using a receptionist object is a little different. Rather than you calling the receptionist, you want the receptionist to call you, when a call is waiting. To arrange this, you first have to tell the receptionist which routine to call when a connection arrives. Since you are asking the receptionist to call you back, the function that the receptionist should call is a callback. Telling the receptionist which callback to use is called registering the callback.

In this tutorial, callbacks are global functions. They take parameters indicating the state being passed by the receptionist, plus one extra parameter, the client data. This is a void* pointer which you provide to the receptionist when registering the callback. You can use this pointer to pass data the worker needs to know about. For example, if the worker is itself an object, then you can pass the address of the worker object to a global callback function as client data, and have the callback function call the appropriate member function of the worker object.

The callback and client data strategy for handling callbacks is used in this tutorial because it is the most straightforward approach. For a very interesting discussion of callbacks, and an awesome C++ approach to callbacks, check out Rich Hickey's article "Callbacks in C++ Using Template Functions" in the February 1995 issue of the C++ Report.

17.5.2 The Receptionist Class

At long last, we are ready to present the sequential receptionist class. Here's the class declaration.

//1The constructor requires an address, a callback function, and client data. The constructor sets up phone_ (declared on line //3) to watch for calls arriving at this address.
//2The answer() member function waits for the next incoming connection, and then responds to it using the callback function. After one call is handled, answer() returns. To continue taking calls, call answer() repeatedly.

Here's how SequentialReceptionist is implemented:

//1The constructor simply initializes its pieces of member data. The initialization of phone_ sets up for reception of incoming calls.
//2The first step in the implementation of answer() is to get the next incoming connection. This is done here.
//3Once we have an incoming connection, the semantics of the sequential receptionist are to pass the connection to a worker for handling. This is done by invoking the callback function.

17.5.3 Using the Sequential Receptionist

To use the receptionist, we need to set up a callback function. Here's a callback that implements the greeting protocol.

All we need to do now is build a receptionist object, register the callback, and let it go. Here's the mainline code.

//1Construct the address on which to wait for connections. This hardwires the address to TCP port 3010.
//2Build the receptionist object. The callback function is registered at construction time.
//3The application runs in an infinite loop, answering one call after another.
//4Handle a single call.
//5Problems with a call are handled by an inner try block and caught here. After an error message is printed, the server goes on and answers the next incoming call. Without the nested try block, any error would cause the entire server application to end. This is not what we want if the error is something like a client resetting the connection.

Previous fileTop of DocumentContentsIndexNext file

©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.