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

`DEMO11_6.CPP[vbar]EXE` contains the new modified multithreaded program and is listed here for reference. Notice the use of arrays to hold the thread handles and IDs:

    // DEMO11_6.CPP - A new version that creates 3

    // secondary threads of execution

    // 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 ///////////////////////////////////////////////////

    #define MAX_THREADS 3

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

    DWORD WINAPI Printer_Thread(LPVOID data);

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

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

    DWORD WINAPI Printer_Thread(LPVOID data)

    {

    // this thread function simply prints out data

    // 25 times with a slight delay

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

        {

        printf("%d ",(int)data+1); // 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[MAX_THREADS];  // this holds the

                                        // handles to the threads

    DWORD  thread_id[MAX_THREADS];      // this holds the ids of the threads

    // start with a blank line

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

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

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

        {

        thread_handle[index] = CreateThread(NULL, // default security

                           0,                 // default stack

                           Printer_Thread,  // use this thread function

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

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

                           &thread_id[index]); // send id back in this var

        } // end for index

    // now enter into printing loop, make sure

    // this takes longer than threads,

    // so threads finish first, note that primary thread prints 4

    for (index=0; index<75; index++)

        {

        printf("4 ");

        Sleep(100);

        } // end for index

    // at this point the threads should all be dead, so close handles

    for (index=0; index<MAX_THREADS; index++)

        CloseHandle(thread_handle[index]);

    // end with a blank line

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

    } // end main

Sample output:

    Starting all threads…

    4 1 2 3 4 1 2 3 4 1 2 3 1 4 2 3 4 1 2 3 1 4 2 3 4

    1 2 3 1 4 2 3 4 1 2 3 1 4 2 3 4 1 2 3 4 1 2 3 4 1

    2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2

    3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3

    4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4

    4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4

    All threads terminated.

Wow! Isn’t that cool? It’s so easy to create multiple threads. Now, if you’re astute, you should be a little weary at this point, and you should question the fact that you used the same function each time for the thread callback. The reason why this works correctly is that all the variables in the code are created on the stack, and each thread has its own stack. So it all works out. Take a look at Figure 11.19 to see this.

Figure 11.19 Primary and secondary thread memory and code space allocation.

Figure 11.19 overlooks something that is very important: termination. Both threads terminated on their own, but the primary thread had no control over this. In addition, the primary thread really had no way to tell if the threads were complete and had terminated (that is, if they had returned).

What you need is a way to communicate between threads and check the status of threads from one another or from the primary thread itself. There is a brute-force way to terminate a thread using `TerminateThread()`, but I suggest that you don’t use this.

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.