When the server process is started, it establishes standard sockets
for clients to connect to it and waits for incoming connections. When
a client connects to the server, the server will fork a new process
(unless -nofork
was specified on the command line) to deal
with incoming requests from the client. The result of this is that
each logical application has its own dedicated request server. This
prevents event handling in one application from blocking event
dispatching in another.
Each request server is essentially an event loop. It waits for an event to occur, and dispatches that event to the appropriate handlers. If the event represents input available on the client connection, it reads the message off the stream and executes the corresponding request. If the event is an X event or a Motif callback, relevant information about that event is packed into a message and sent to the Lisp client. After sending the event notification, the server will enter a callback event loop to allow processing of requests from the client’s callback procedure. However, during the callback event loop, only input events from the client will be processed; all other events will be deferred until the callback is terminated.
The server supports a standard means for reading and writing data
objects into messages for communication with the Lisp client. For
every available type of data which may be transported there are reader
and writer functions. For instance, WIDGET
is a valid type
for argument data. Two functions are defined in the server:
message_read_widget()
and
message_write_widget()
. To allow for a more generalized
interface to argument passing, the server defines the functions
toolkit_write_value()
and toolkit_read_value()
.
These functions are passed data and a type identifier; it is their job
to look up the correct reader/writer function. Clearly, if the type
of an argument is known at compile time then it is best to use the
specific reader/writer functions. However, if such type information
is not known at compile time, as is the case with arbitrary resource
lists, the higher level toolkit_xxx_value()
functions are
the only available options.