Chapter 21 -- Thread-Local Storage

[Previous] [Next]

Chapter 21

Sometimes it's helpful to associate data with an instance of an object. For example, window extra bytes associate data with a specific window by using the SetWindowWord and SetWindowLong functions. You can use thread-local storage (TLS) to associate data with a specific thread of execution. For example, you can associate the creation time of a thread with a thread. Then, when the thread terminates, you can determine the thread's lifetime.

The C/C++ run-time library uses TLS. Because the library was designed years before multithreaded applications, most functions in the library are intended for use with single-threaded applications. The strtok function is an excellent example. The first time an application calls strtok, the function passes the address to a string and saves the address of the string in its own static variable. When you make future calls to strtok, passing NULL, the function refers to the saved string address.

In a multithreaded environment, one thread might call strtok, and then, before it can make another call, another thread might also call strtok. In this case, the second thread causes strtok to overwrite its static variable with a new address without the first thread's knowledge. The first thread's future calls to strtok use the second thread's string, which can lead to all kinds of bugs that are difficult to find and to fix.

To address this problem, the C/C++ run-time library uses TLS. Each thread is assigned its own string pointer that is reserved for use by the strtok function. Other C/C++ run-time functions that require the same treatment include asctime and gmtime.

TLS can be a lifesaver if your application relies heavily on global or static variables. Fortunately, developers tend to minimize the use of such variables and rely much more on automatic (stack-based) variables and data passing via function parameters. This is good because stack-based variables are always associated with a particular thread.

The standard C run-time library has been implemented and reimplemented by various compiler vendors; a C compiler wouldn't be worth buying if it didn't include the standard C library. Programmers have used it for years and will continue to do so, which means that the prototype and behavior of functions such as strtok must remain exactly as the standard C library describes them. If the C run-time library were to be redesigned today, it would be designed for environments that support multithreaded applications, and extreme measures would be taken to avoid the use of global and static variables.

In my own software projects, I avoid global variables as much as possible. If your application uses global and static variables, I strongly suggest that you examine each variable and investigate the possibilities for changing it to a stack-based variable. This effort can save you an enormous amount of time if you decide to add threads to your application, and even single-threaded applications can benefit.

You can use the two TLS techniques discussed in this chapter—dynamic TLS and static TLS—in both applications and DLLs. However, they're generally more useful when you create DLLs because DLLs often don't know the structure of the application to which they are linked. When you write an application, however, you typically know how many threads will be created and how those threads will be used. You can then create makeshift methods or, better yet, use stack-based methods (local variables) for associating data with each created thread. Nevertheless, application developers can also benefit from the information in this chapter.



Programming Applications for Microsoft Windows
Programming Applications for Microsoft Windows (Microsoft Programming Series)
ISBN: 1572319968
EAN: 2147483647
Year: 1999
Pages: 193

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net