Line-Oriented Messages, DLL Entry Points, and TLS
serverSK and clientSK communicate using messages, where each message is composed of a 4-byte length header followed by the message content. A common alternative to this approach is to have the messages delimited by end-of-line (or new-line) characters.The difficulty with delimited messages is that there is no way to know the message length in advance, and each incoming character must be examined. Receiving a single character at a time would be inefficient, however, so incoming characters are stored in a buffer, and the buffer contents might include one or more end-of-line characters and parts of one or more messages. Buffer contents and state must be retained between calls to the message receive function. In a single-threaded environment, static storage can be used, but multiple threads cannot share the same static storage.In more general terms, we have a multithreaded persistent state problem. This problem occurs any time a thread-safe function must maintain information from one call to the next. The Standard C library strtok function, which scans a string for successive instances of a token, is a common alternative example of this problem.
Solving the Multithreaded Persistent State Problem
The solution requires a combination of the following components.
- A DLL for the message send and receive functions.
- An entry point function in the DLL.
- Thread Local Storage (TLS, Chapter 7). The DLL index is created when the process attaches, and it is destroyed when the process detaches. The index number is stored in static storage to be accessed by all the threads.
- A structure containing a buffer and its current state. A structure is allocated every time a thread attaches, and the address is stored in the TLS entry for that thread. A thread's structure is deallocated when the thread detaches.
The TLS, then, plays the role of static storage, and each thread has its own unique copy of the static storage.