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

If the function succeeds, the return value indicates the event that caused the function to return. If the function fails, the return value is `WAIT_FAILED`. To get extended error information, call `GetLastError()`. The return value upon success is one of the following values in bold:

  • `WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount - 1)`—If `bWaitAll` is `TRUE`, the return value indicates that the state of all specified objects is signaled. If `bWaitAll` is `FALSE`, the return value minus `WAIT_OBJECT_0` indicates the `lpHandles` array index of the object that satisfied the wait. If more than one object became signaled during the call, this is the array index of the signaled object with the smallest index value of all the signaled objects.
  • `WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount – 1)`—If `bWaitAll` is `TRUE`, the return value indicates that the state of all specified objects is signaled and at least one of the objects is an abandoned mutex object. If `bWaitAll` is `FALSE`, the return value minus `WAIT_ABANDONED_0` indicates the `lpHandles` array index of an abandoned mutex object that satisfied the wait.
  • `WAIT_TIMEOUT`—The time-out interval elapsed and the conditions specified by the `bWaitAll` parameter are not satisfied.

`WaitForMultipleObjects()` determines whether the conditions exist that satisfy the wait. If the wait is not satisfied, the calling thread enters an efficient wait state, consuming very little processor time, while waiting for one of the conditions of the wait to be satisfied.

Using Signaling to Synchronize Threads

These explanations are very technical. So, as an example of how to use these functions, you’re going to make another slight change to the program you’ve been working with. For the next version, you’re going to remove the global termination signal flag and create a main loop that simply calls `WaitForSingleObject()`.

The only reason that you’re removing the global terminate message is to make the program simpler. This is still the best way to tell threads to terminate; it’s just that sitting in a busy loop is not the best way to test if they’ve actually terminated.

And that is why you’re going to use the `WaitForSingleObject()` call. This call sits in a virtual wait loop that eats very little processor time. Also, because `WaitForSingleObject()` can only wait for one signal, and thus one thread, to terminate, this example will only have one secondary thread.

In a moment, you’ll rewrite the program to contain three threads, and you’ll use `WaitForMultipleObjects()` to wait for all of them to terminate. Anyway, `DEMO11_8.CPP[vbar]EXE` uses `WaitForSingleObject()` and creates one extra thread. Take a look at the code:

    // DEMO11_8.CPP - A single threaded example of

    // WaitForSingleObject(…).

    // INCLUDES //////////////////////////////////////////////////////////

    #define WIN32_LEAN_AND_MEAN  // make sure certain

                                 // headers are included correctly

    #include <windows.h>   // include the standard windows stuff

    #include <windowsx.h>  // include the 32 bit stuff

    #include <conio.h>

    #include <stdlib.h>

    #include <stdarg.h>

    #include <stdio.h>

    #include <math.h>

    #include <io.h>

    #include <fcntl.h>

    // DEFINES //////////////////////////////////////////////////////////

    // PROTOTYPES //////////////////////////////////////////////////////

    DWORD WINAPI Printer_Thread(LPVOID data);

    // GLOBALS /////////////////////////////////////////////////////////

    // FUNCTIONS //////////////////////////////////////////////////////

    DWORD WINAPI Printer_Thread(LPVOID data)

    { // this thread function simply prints out data 50

    // times with a slight delay

    for (int index=0; index<50; index++)

        {

        printf("%d ",data); // output a single character

        Sleep(100);         // sleep a little to slow things down

        } // end for index

    // just return the data sent to the thread function

    return((DWORD)data);

    } // end Printer_Thread

    // MAIN ///////////////////////////////////////////////////////

    void main(void)

    {

    HANDLE thread_handle;  // this is the handle to the thread

    DWORD  thread_id;      // this is the id of the thread

    // start with a blank line

    printf("\nStarting threads…\n");

    // create the thread, IRL we would check for errors

    thread_handle = CreateThread(NULL, // default security

                  0,               // default stack

                  Printer_Thread,  // use this thread function

                  (LPVOID)1,         // user data sent to thread

                  0,             // creation flags, 0=start now.

                  &thread_id);         // send id back in this var

    // now enter into printing loop, make sure

    // this is shorter than the thread,

    // so thread finishes last

    for (int index=0; index<25; index++)

        {

        printf("2 ");

        Sleep(100);

        } // end for index

    // note that this print statement may get

    // interspliced with the output of the

    // thread, very key!

    printf("\nWaiting for thread to terminate\n");

    // at this point the secondary thread so still be working,

    // now we will wait for it

    WaitForSingleObject(thread_handle, INFINITE);

    // at this point the thread should be dead

    CloseHandle(thread_handle);

    // end with a blank line

    printf("\nAll threads terminated.\n");

    } // end main

Sample output:

    Starting threads…

    2 1 2 1 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1

    1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1

    Waiting for thread to terminate

    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    All threads terminated.

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.