Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C++
Article

How to use WIN32 Event Kernel Object

Rate me:
Please Sign up or sign in to vote.
3.69/5 (41 votes)
7 Sep 20044 min read 133.3K   1.2K   55   11
Thread synchronization using WIN32 Event Kernel object.

Introduction

Thread synchronization is a problem domain as there are many ways to handle it. There are enough books and articles that show how to avoid multiple threads related nightmare. While working on this nightmare, I come across WIN32 events (WIN32 Kernel objects). Initially, I was unable to understand how to use global kernel objects across threads using global variables; that itself creates hell, but after understanding it, I found it very easy to use. Here, I will explain the usage of WIN32 events in context of Auto and Manual Reset Events.

About WIN32 Events

WIN32 Events are kernel objects and like other kernel objects available across process boundaries. A WIN32 Event works like a state machine and spends its life between two states, i.e., signaled state and non signaled state. An event is in signaled state means that it has the capacity to release the threads waiting for this event to be signaled. An event is in non signaled state means that it will not release any thread that is waiting for this particular event.

Using WIN32 Auto Reset Event

An Auto Reset Event is the event which will guarantee to release a single thread that is waiting on this event to occur and returns back to non signaled state. If more than one thread is waiting for this event to occur then which thread will be released is random.

Creating and using WIN32 Events make use of WIN32 APIs. Some of the APIs are:

CreateEvent(...); // API to Create Event
CreateThread(...); // API to Create Thread
// API for Waiting for an Event
WaitForSingleObject (...); 
WaitForMultipleObject (...);
OpenHandle(...); // API to get Event Handles
SetEvent(...); // API to put an event in signaled state.
ResetEvent(...); // API to put an event in non signaled state.
CloseHandle(...); // API to close Event Handles

Let's see the code which will use an auto reset event. The scenario is that the main program will create a thread and the thread will wait for an event to get signaled twice. The main program will signal the event and wait for the thread to die.

// Standard include headers
#include <windows.h>
#include <iostream>
using namespace std;

DWORD WINAPI Tf ( LPVOID n )
{
    cout<<"Thread Instantiated........."<<endl;
    // Get the handler to the event for which we need to wait in 
    //    this thread.
    HANDLE hEvent = OpenEvent ( EVENT_ALL_ACCESS , false, "MyEvent" );
    if ( !hEvent ) { return -1; }
    // Loop through and wait for an event to occur
    for ( char counter = 0; counter < 2; counter ++ )
    {
        // Wait for the Event
        WaitForSingleObject ( hEvent, INFINITE );
        //    No need to Reset the event as its become non signaled as soon as
        //    some thread catches the event.
        cout<<"Got The signal......."<<endl;
    }
    CloseHandle(hEvent);
    cout<<"End of the Thread......"<<endl;
    return 0;
}

int main()
{
    //    Create an Auto Reset Event which automatically reset to 
    //    Non Signalled state after being signalled
    HANDLE     hEvent = CreateEvent ( NULL , false , false , "MyEvent" );
    if ( !hEvent ) return -1;
    //    Create a Thread Which will wait for the events to occur
    DWORD Id;
    HANDLE hThrd = CreateThread ( NULL, 0, (LPTHREAD_START_ROUTINE)Tf,0,0,&Id );
    if ( !hThrd ) { CloseHandle (hEvent); return -1; }
    // Wait for a while before continuing....
    Sleep ( 1000 );
    // Give the signal twice as the thread is waiting for 2 signals to occur
    for ( char counter = 0; counter < 2; counter ++ )
    {
        // Signal the event
        SetEvent ( hEvent );
        // wait for some time before giving another signal
        Sleep ( 2000 );
    }
    // Wait for the Thread to Die
    WaitForSingleObject ( hThrd, INFINITE );
    
    CloseHandle ( hThrd );
    CloseHandle ( hEvent );
    cout<<"End of Main ........"<<endl;
    return 0;
}

Code Description

The above code calls CreateEvent ( NULL , false , false , "MyEvent" ); to create an event. The parameter descriptions are given below:

  1. First parameter NULL represents default security attributes.
  2. Second parameter is a flag to Manual reset event. false means the event will be an auto reset event, and manual reset event if the flag is true.
  3. Third parameter is a flag to the state of the event being created. If false the event will be created in non signaled state, and if true the event will be created in signaled state. An event being created in signaled state means that first thread which is waiting for the signal will be released without any call to SetEvent(...); in case of an Auto Reset Event. In case of Manual Reset Event, all threads will be released that are waiting for this signal unless there is a call of ResetEvent(...).
  4. Fourth parameter is the name of the event with which it will be identified globally. If an event with the same name as above already exists then handle to the existing event will open.

The code then creates a thread by calling CreateThread(...) API. We can also use C run time library function beginthreadex(...) for creating the thread. The loop runs twice and signals the events after two seconds using SetEvent(...) API. This API takes the handle to the thread.

After signaling the event, the main program waits for the thread to die using WaitForSingleObject(...). The program must close the handle because leaving the handle will have a memory leak.

The thread uses OpenEvent ( EVENT_ALL_ACCESS , false, "MyEvent" ); to get the handle to the event. Note that we can access the events only by unique names, so names must be unique. The parameter descriptions are given below:

  1. First parameter allows the thread to wait for this particular event signal.
  2. Second parameter will not allow the events to be inheritable.
  3. Third parameter is the name of the event for which we required a handle.

Using WIN32 Manual Reset Event

An event is called Manual reset event if it has the capacity of releasing as many number of threads which are waiting for this particular event until there is an explicit API call for resetting the event in non signaled state. Creating a manual reset event can be done just by changing the second parameter of the CreateEvent(...); API call. To create a manual reset event, we will call this API as CreateEvent ( NULL , true , false , "MyEvent" );.

Rest of the program will be similar to that of the auto reset event except that we need to call ResetEvent(...) API. The code is given below:

#include <windows.h>
#include <iostream>
using namespace std;

DWORD WINAPI Tf ( LPVOID n )
{
    cout<<"Thread Instantiated........."<<endl;
    // Get the handler to the event for which we need to wait in 
    //    this thread.
    HANDLE hEvent = OpenEvent ( EVENT_ALL_ACCESS , false, "MyEvent" );
    if ( !hEvent ) { return -1; }
    // Loop through and wait for an event to occur
    for ( char counter = 0; counter < 2; counter ++ )
    {
        // Wait for the Event
        WaitForSingleObject ( hEvent, INFINITE );
        // We need to reset the event since the event is manual reset
        //    event
        ResetEvent ( hEvent );
        cout<<"Got The signal......."<<endl;
    }
    CloseHandle ( hEvent );
    cout<<"End of the Thread......"<<endl;
    return 0;
}

int main()
{
    //    Create an Manual Reset Event where events must be reset 
    //    manually to non signalled state
    HANDLE     hEvent = CreateEvent ( NULL , true , false , "MyEvent" );
    if ( !hEvent ) return -1;
    //    Create a Thread Which will wait for the events to occur
    DWORD Id;
    HANDLE hThrd = CreateThread ( NULL, 0, (LPTHREAD_START_ROUTINE)Tf,0,0,&Id );
    if ( !hThrd ) { CloseHandle (hEvent); return -1; }
    // Wait for a while before continuing....
    Sleep ( 1000 );
    // Give the signal twice as the thread is waiting for 2 signals to occur
    for ( char counter = 0; counter < 2; counter ++ )
    {
        // Signal the event
        SetEvent ( hEvent );
        // wait for some time before giving another signal
        Sleep ( 2000 );
    }
    // Wait for the Thread to Die
    WaitForSingleObject ( hThrd, INFINITE );
    
    CloseHandle ( hThrd );
    CloseHandle ( hEvent );
    cout<<"End of Main ........"<<endl;
    return 0;
}

History

In continuation of this, I will explain the usage and difference between different Event signaling APIs like PulseEvent(...) and SetEvent(...) etc., in my next article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect
India India
A programmer by heart since 1998. Written code in C++, Java, JavaScript, Python & Ruby, Worked on Stack Development to Web Development. Data Specialist with SQL and NoSQL DBs

Comments and Discussions

 
GeneralMy vote of 4 Pin
Francis Monkman2-Apr-13 22:49
Francis Monkman2-Apr-13 22:49 
GeneralMy vote of 4 Pin
VEMS15-Oct-12 6:22
VEMS15-Oct-12 6:22 
GeneralMy vote of 5 Pin
tiger_敏1-Apr-11 1:37
tiger_敏1-Apr-11 1:37 
QuestionHow can we check whether a application loaded Pin
JothiMurugeswaran11-Oct-07 1:31
JothiMurugeswaran11-Oct-07 1:31 
QuestionShould SetEvent(hEvent ) be added in the thread funciton? Pin
Eric Vonjacson22-May-06 19:50
Eric Vonjacson22-May-06 19:50 
AnswerRe: Should SetEvent(hEvent ) be added in the thread funciton? Pin
itsdkg22-May-06 19:58
itsdkg22-May-06 19:58 
GeneralRe: Should SetEvent(hEvent ) be added in the thread funciton? Pin
OuaisBla28-Mar-07 4:19
OuaisBla28-Mar-07 4:19 
GeneralFlimsy example code Pin
Eric Kenslow8-Sep-04 7:39
Eric Kenslow8-Sep-04 7:39 
GeneralRe: Flimsy example code Pin
itsdkg8-Sep-04 18:50
itsdkg8-Sep-04 18:50 
GeneralRe: Flimsy example code Pin
Member 85553611-Jan-09 16:49
Member 85553611-Jan-09 16:49 
Excellent! fairly clear.
GeneralNice Pin
vobject7-Sep-04 22:11
vobject7-Sep-04 22:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.