A queue can be used to pass information between the process that created it and other processes in the system. The process that creates the queue is known as the owner of the queue, and is the only process that can read and remove elements from the queue. Other processes may only add elements to the queue.
In a client-server environment, a queue is typically created by the server process. If a requester wishes to receive returned data from the server process, it must therefore create its own queue. Figure "Interprocess Communication Using Queues (Part 1)" shows a requester process using the DosCreateQueue() function to create its own queue, as well as using a queue owned by a server process.
Queues may be created with a number of different ordering mechanisms. The order of elements in a queue is determined when the queue is created, and may be specified as FIFO, LIFO, or priority-based. When adding an element to a priority-based queue, a process must specify a priority (from 0 to 15 with 0 being lowest and 15 being highest) for the element.
Processes other than a queue's owner may gain write access to the queue using the DosOpenQueue() function to obtain a queue handle. Once this handle is obtained, the process may use the DosWriteQueue() function to add elements to the queue. The example in Figure "Interprocess Communication Using Queues (Part 1)" shows a requester process that passes a request to a server process using a queue created by that server process.
The requester process first creates its own queue for returned data, using the DosCreateQueue() function. This queue will be accessed by the server to write the returned data from the completed request, which can then be read by the requester. The example shown in Figure "Interprocess Communication Using Queues (Part 2)" creates a FIFO queue with the name specified in the string constant REQQUENAME, and specifies that the addresses of any elements placed in the queue by 16-bit processes are to be automatically converted to 32-bit addresses by the operating system. This conversion, specified using the QUE_CONVERT_ADDRESS flag, is used by 32-bit queue owners to avoid the need for the queue owner to explicitly convert addresses.
The requester obtains access to the server's queue using the DosOpenQueue() function, passing the queue name as a parameter. This function returns both a queue handle and the process identifier of the server process that owns the queue.
The requester must allocate a shared memory object to contain the request; the actual queue element contains only a pointer to that memory object. The requester then invokes the DosGiveSharedMem() function to provide read-only access (by specifying only the PAG_READ flag) to that object for the server process, using the process identifier returned by the DosOpenQueue() function.
The requester adds its request as a element in the queue, using the DosWriteQueue() function. Note that the second parameter to the function is an unsigned long integer, which may be used to pass application-specific information. The value specified in this parameter is passed to the queue owner as the ulData field of a REQUESTDATA structure, which is returned by the DosReadQueue() function. In this example, the parameter is used to pass the window handle of the requester's object window to the server process, so that a notification message can be passed to the requester when the request has been completed.
Once the element has been written to the queue, the requester immediately relinquishes access to the server's queue by issuing a DosCloseQueue() function call. The shared memory object allocated for the request buffer is then released by the requester using the DosFreeMem() function.
The server process is very similar in structure to the requester, in that it creates its own queue, then awaits and services requests. The server process is illustrated in Figure "Interprocess Communication Using Queues (Part 2)".
Note that the server process does not use an object window. It simply accepts requests from its own queue, using the DCWW_WAIT flag to suspend itself in the DosReadQueue() call until an element becomes available in the queue. Once a request is complete, the server places the returned data on the requester's queue, extracts the window handle of the requester from the REQUESTDATA structure provided by the DosReadQueue() call, and posts a message to the requester indicating that the request is complete. This message is processed by the requester to retrieve the returned data from the queue. Continue on the next page of this chapter.