Multi Threading Tutorial

 

 

www.cpp-home.com

www.code-dynasty.net

 

www.supercamel.co.nr  < this is my homepage.

 

A thread is a unit of execution for your application. Most programs execute instructions sequentially from the start to the end of your code. Multi threading allows more than one thread of execution. Basically this means you can do more than one thing at the same time. Imagine having two functions execute at once. Of course the CPU cannot actually execute two code paths simultaneously so it switches between threads during normal program flow. However, on a multi processor machine employing Symmetric Multi-Processing (SMP) more than one CPU can execute our program simultaneously.  SMP is not supported by older versions of Windows (95/98/ME). A program carefully designed for multithreaded execution can outperform a single-threaded application in many circumstances. For example, one thread can handle sockets while another can handle the GUI. Each thread runs on a different application stack.

 

Have a look at this function

 

WINBASEAPI HANDLE WINAPI CreateThread

            (LPSECURITY_ATTRIBUTES, DWORD, LPTHREAD_START_ROUTINE, PVOID, DWORD, PDWORD);

 

The first parameter is a pointer to a security attributes structure. In this tutorial I will leave it as NULL.  The second parameter is the size of the stack that you want the thread to run on. In this tutorial I will leave it at 0 to tell Windows NT that we want it to be the same size as the applications primary thread. The third parameter is the address of a function that you want your thread to execute. CreateThread expects this function to be declared as WINAPI. The fourth parameter is an argument that will be given to your threads function. It can be anything you want. The fifth parameter can be either 0 or CREATE_SUSPENDED. If you provide CREATE_SUSPENDED then your thread wont execute until you call ResumeThread(). If it is 0 then your thread will execute as soon as it is created. The last parameter is the address of an integer that will receive a unique thread ID. Every thread ID is different. The return value of this function is a handle to the thread.

 

Now we have that covered, lets make a thread!

 

__________________________________________________________________________________________________________________________________________________________

 

#include <iostream>

#include <windows.h>

 

using namespace std;

 

 

 

long WINAPI Thread()

{

    //print this on the screen

    cout << "Testing\n";                                              

}

 

 

 

//execution starts here

int main()                                                            

{

   

    //we create a thread that will execute Thread()

    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, 0, 0, 0);   

 

    //Sleep so the user can see the output displayed by the other thread

    Sleep(3000);                                                       

}

 

__________________________________________________________________________________________________________________________________________________________

 

This is about as simple as multithreading gets. When the program executes, it immediately creates a thread. This thread outputs text while the main thread sleeps. Basically main() and thread() execute at the same time. These threads are completely unsynchronised.

 

The next example passes a variable to the thread function.

 

#include <iostream>

#include <windows.h>

 

using namespace std;

 

class ThreadInfo

{

    public:

        int a, b, c;

};

 

 

 

//Thread() receives a pointer to threadinfo

 

long WINAPI Thread(ThreadInfo *threadinfo)                                    

{

    threadinfo -> a = 100;                                                   

    threadinfo -> b = 200;

 

    //we change around with the values in threadinfo

    threadinfo -> c = threadinfo -> a * threadinfo -> b;

}

 

int main()

{

    ThreadInfo threadinfo;

 

    //Create the thread

    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, &threadinfo, 0, 0);

 

 

    //Wait for a moment to let the thread finish executing

    Sleep(100);

 

 

    //print threadinfo.c on the screen

    cout << threadinfo.c << endl;

 

 

    //Pause for a moment                                           

    Sleep(3000);

}

 

First I have created a class with some integers in it. In the CreateThread function I provide a pointer to this class. The CreateThread() function provides this as the parameter for the Thread() function.  There is one problem, the first call to Sleep() is a bit of a shot in the dark. We don’t know for sure that the thread has finished .Obviously if this function hasn’t returned within 0.1 seconds then something is wrong, but that isn’t the point. The WaitForSingleObject() function solves this problem.

 

WINBASEAPI DWORD WINAPI WaitForSingleObject(HANDLE,DWORD);

 

WaitForSingleObject() waits until either the thread has terminated or the timeout value provided in the second parameter has elapsed. For this function we need the handle of the thread. MSDN recommends that all handles are closed with the CloseHandle() function before the program terminates.

 

So . . .

 

#include <iostream>

#include <windows.h>

 

using namespace std;

 

class ThreadInfo

{

    public:

        int a, b, c;

};

 

 

//Thread() receives a pointer to threadinfo

long WINAPI Thread(ThreadInfo *threadinfo)                                    

{

 

    threadinfo -> a = 100;                                                   

    threadinfo -> b = 200;

   

    //we change around with the values in threadinfo

    threadinfo -> c = threadinfo -> a * threadinfo -> b;

 

}

 

 

 

int main()

{

    ThreadInfo threadinfo;

 

    //Create the thread

    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, &threadinfo, 0, 0);

 

    //Wait for the thread to finish

    WaitForSingleObject(hThread, 100);                                                         

 

    //Close the handle

    CloseHandle(hThread);                                                                     

 

    //print threadinfo.c on the screen

    cout << threadinfo.c << endl; 

 

    //Pause for a moment                                                            

    Sleep(3000);

}

 

Here are some other useful functions. Check out MSDN for more info

 

 

WINBASEAPI DWORD WINAPI SuspendThread(HANDLE);

 

WINBASEAPI DWORD WINAPI ResumeThread(HANDLE);

 

WINBASEAPI HANDLE WINAPI GetCurrentThread(void);

 

WINBASEAPI BOOL WINAPI GetExitCodeThread(HANDLE,PDWORD);

 

WINBASEAPI BOOL WINAPI TerminateThread(HANDLE,DWORD);

 

 

SuspendThread() pauses a threads execution. The threads execution can be resumed with ResumeThread(). GetCurrentThread() returns a handle to the thread that the function was executed in. GetExitCodeThread retrieves the return value of a thread. TerminateThread() immediately terminates a thread.

 

Here’s a demo . . .

__________________________________________________________________________________________________________________________________________________________

 

 

#include <windows.h>

#include <stdio.h>

 

long WINAPI ThreadFunc()

{

    HANDLE hThisThread = GetCurrentThread();

    SuspendThread(hThisThread);

    CloseHandle(hThisThread);

    return 12345;

}

 

int WINAPI WinMain (HINSTANCE hThisInstance,

                    HINSTANCE hPrevInstance,

                    LPSTR lpszArgument,

                    int nFunsterStil)

 

{

 

    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc, 0, 0, 0);

    MessageBox(NULL, "Test", "Test", MB_OK);

    ResumeThread(hThread);

    WaitForSingleObject(hThread, INFINITE);

    DWORD a;

    GetExitCodeThread(hThread, &a);

    CloseHandle(hThread);

    char msg[128];

    sprintf(msg, "%d", a);

    MessageBox(NULL, msg, "Test", MB_OK);

}

 

If this helps, send me an email

 

Samuel.supercamel@gmail.com