Tricks of the Windows Game Programming Gurus:Algorithms, Data Structures, Memory Management, and Multithreading

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

#### Conjuring a Thread from the Plasma Pool

You’ll be using console applications for the examples that follow, so once again, please compile the programs correctly. (I’m only belaboring this because every hour I get 30-60 emails on various books I’ve written from people using the VC++ compiler wrong. Doesn’t anyone read the introductions?)

However, there is one more caveat: You must use the multithreaded libraries for these examples. You do this by going into the main menu in MS DEV Studio, under Build, Settings, Code Generation, and setting the library to multithreaded. This is also shown in Figure 11.18. Also, make sure to turn optimization off. It can confuse the multithreaded synchronization code sometimes, so better safe than sorry.

Figure 11.18 Creating a console application with multithreaded libraries.

> Note: I just had deja vu. Or was it really deja vu, or just a glitch in the simulation?

> If you didn’t get that, you won’t know what it was you didn’t get so it won’t matter anyway. :)

All righty then, let’s get started. Creating a thread is easy; it’s keeping it from destruction that’s the hard part! The Win32 API call is as follows:

    HANDLE CreateThread(

    LPSECURITY_ATTRIBUTES  lpThreadAttributes,

           // pointer to thread security attributes

     DWORD  dwStackSize,  // initial thread stack size, in bytes

     LPTHREAD_START_ROUTINE  lpStartAddress,

                  // pointer to thread function

     LPVOID  lpParameter,      // argument for new thread

     DWORD  dwCreationFlags,   // creation flags

     LPDWORD  lpThreadId);    // pointer to returned thread identifier

`lpThreadAttributes` points to a `SECURITY_ATTRIBUTES` structure that specifies the security attributes for the thread. If `lpThreadAttributes` is `NULL`, the thread is created with a default security descriptor and the resulting handle is not inherited.

`dwStackSize` specifies the size, in bytes, of the stack for the new thread. If 0 is specified, the stack size defaults to the same size as that of the primary thread of the process. The stack is allocated automatically in the memory space of the process, and it is freed when the thread terminates. Note that the stack size grows, if necessary.

`CreateThread` tries to commit the number of bytes specified by `dwStackSize`, and fails if the size exceeds available memory.

`lpStartAddress` points to the application-supplied function to be executed by the thread and represents the starting address of the thread. The function accepts a single 32-bit argument and returns a 32-bit exit value.

`lpParameter` specifies a single 32-bit parameter value passed to the thread.

`dwCreationFlags` specifies additional flags that control the creation of the thread. If the `CREATE_SUSPENDED` flag is specified, the thread is created in a suspended state and will not run until the `ResumeThread()` function is called. If this value is zero, the thread runs immediately after creation.

`lpThreadId` points to a 32-bit variable that receives the thread identifier.

If the function succeeds, the return value is a handle to the new thread. If the function fails, the return value is `NULL`. To get extended error information, call `GetLastError()`.

The function call might look a bit complex, but it’s really not. It just allows a lot of control. You won’t use much of its functionality in most cases.

When you’re done with a thread, you need to close its handle; in other words, let the operating system know that you’re done using the object. This is done with the `CloseHandle()` function call, which uses the handle returned by `CreateThread()` and reduces the reference count in the kernel object that refers to the thread by 1.

You need to do this for every thread when you’re done with it. This does not kill the thread; it just tells the OS that the thread is dead. The thread must terminate itself, be told to terminate (with `TerminateThread()`), or be terminated by the OS when the main thread or primary thread terminates. We’ll get to all that later, but for now, just realize that this is a clean-up call that needs to be done before you exit a multithreaded app. Here is the function prototype:

    BOOL CloseHandle(HANDLE  hObject);    // handle to object to close

`hObject` identifies an open object handle. If the -function succeeds, the return value is `TRUE`. If the function fails, the return value is `FALSE`. To get extended error information, call `GetLastError()`. Furthermore, `CloseHandle()` closes handles to the following objects:

  • Console input or output
  • Event files
  • File mappings
  • Mutexes
  • Named pipes
  • Processes
  • Semaphores
  • Threads

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.