Showing posts with label Thread Synchronisation. Show all posts
Showing posts with label Thread Synchronisation. Show all posts

Tuesday, 15 February 2011

Debugging Mutex and Locks

When there are multiple Mutex's in the program, it may be required to find if a particular thread is locked far longer than necessary. This can cause problems and the output may not be what is expected.

To get round this, I took an old example from here and modified it to help me print some debugging info.

I modified the printSomething() in Singleton.h to add a sleep as follows:



  void printSomething(char *name, int count)
{

Lock guard(mutex_);
Sleep(10);
Lock guard2(mutex_);
std::cout << name << " loop " << count << std::endl;
}




and I modified the Mutex.h as follows:



//Example from http://www.relisoft.com/Win32/active.html
#if !defined _MUTEX_H_
#define _MUTEX_H_

class
Mutex
{

friend class
Lock;
public
:
Mutex () { InitializeCriticalSection (& _critSection); }
~
Mutex () { DeleteCriticalSection (& _critSection); }
private
:
void
Acquire ()
{

DWORD start = GetTickCount();
EnterCriticalSection (& _critSection);
DWORD elapsed = GetTickCount() - start;
if
(elapsed > 15)
{

//Debugging Info
std::cout<<"Debugging Info: Waited at mutex for "<<elapsed<<std::endl;
}
}

void
Release ()
{

LeaveCriticalSection (& _critSection);
}


CRITICAL_SECTION _critSection;
};


#endif



The output is as follows:
ImageThe small problem with the above approach is that if a Thread is deadlocked, we may not get the debug output as we would have to kill the process.

Wednesday, 10 February 2010

Synchronous and Asynchronous calls in C++

Sometimes there can be confusion between Synchronous and Asynchronous calls. A synchronous call is the one in which the function/call/procedure has to return before the next statement can be executed. What this means is that the function is blocking the rest of the code.

In asynchronous calling, generally there would be multiple threads. So a function call on one thread will probably not block the function call on other thread. That means that both the functions are asynchronous.

Here is a simple example that I have modified from an earlier example to show synchronous and asynchronous calling:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Example from http://www.adrianxw.dk/SoftwareSite/Threads/Threads2.html
//This shows an example of Synchronous and Asynchronous function calls
#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;

void
Func1(void *);
void
Func2(void *);

CRITICAL_SECTION Section; //This will act as Mutex


int
main()
{

InitializeCriticalSection(&Section);

//Synchronous calling
cout<<"\nSynchronous calling"<<endl;
Func1(0);
Func2(0);

//Asynchronous calling
cout<<"\nAsynchronous calling"<<endl;
HANDLE hThreads[2];

//Create two threads and start them
hThreads[0] = (HANDLE)_beginthread(Func1, 0, NULL);
hThreads[1] = (HANDLE)_beginthread(Func2, 0, NULL);

//Makes sure that both the threads have finished before going further
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);

//This is done after all threads have finished processing
DeleteCriticalSection(&Section);

cout << "Main exit" << endl;
return
0;
}


void
Func1(void *P)
{

int
Count;

for
(Count = 1; Count < 11; Count++)
{

EnterCriticalSection(&Section);
cout << "Func1 loop " << Count << endl;
LeaveCriticalSection(&Section);
Sleep(1000);
}

return
;
}


void
Func2(void *P)
{

int
Count;

for
(Count = 10; Count > 0; Count--)
{

EnterCriticalSection(&Section);
cout << "Func2 loop " << Count << endl;
LeaveCriticalSection(&Section);
Sleep(1000);
}

return
;
}







The output is as follows:
Image

Monday, 25 May 2009

Thread Synchronization with Events

Here is an example of using Event with multiple threads for Thread Sync.

Event.h

//Example from http://www.relisoft.com/Win32/active.html
#if !defined _EVENT_H_
#define _EVENT_H_

class
Event
{

public
:
Event ()
{

// start in non-signaled state (red light)
// auto reset after every Wait
_handle = CreateEvent (0, FALSE, FALSE, 0);
}

~
Event ()
{

CloseHandle (_handle);
}


// put into signaled state
void Release () { SetEvent (_handle); }
void
Wait ()
{

// Wait until event is in signaled (green) state
WaitForSingleObject (_handle, INFINITE);
}

operator
HANDLE () { return _handle; }

private
:
HANDLE _handle;
};


#endif



Thread.cpp

//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//This shows example of Multithreading, thread sync, Events
#include <windows.h>
#include <process.h>
#include <iostream>
#include "Event.h"

using namespace
std;

void
Func1(void *);
void
Func2(void *);

Event _event; //Create an event

int
main()
{

HANDLE hThreads[2];

//Create two threads and start them
hThreads[0] = (HANDLE)_beginthread(Func1, 0, NULL);
hThreads[1] = (HANDLE)_beginthread(Func2, 0, NULL);

//Makes sure that both the threads have finished before going further
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);

cout << "Main exit" << endl;
return
0;
}


void
Func1(void *P)
{

int
Count = 0;

for
(;;)
{

_event.Wait();
do
//This loop will only start when Event is triggered
{
cout<<"Func1: Count = "<<Count++<<endl;
}
while(Count < 10);
return
;
}


return
;
}


void
Func2(void *P)
{

for
(int i = 0; i < 10; i++)
{

cout<<"Func2: i = "<<i<<endl;
}

//Release the event so Thread1 (Func1) can start
_event.Release();
return
;
}




You can also have a look at this example here which uses Event, Mutex, etc.

The output is as follows:

Image

Monday, 11 May 2009

Another Multi-Threading example with Mutex

Here is an example where we combine the previous programs to create a multi-threaded mutex based program. If you havent already seen, then please check out the Singleton class and Multi-Threading with Thread Sync.

We are going to have some .h files in this example.

Lock.h

//Example from http://www.relisoft.com/Win32/active.html
#if !defined _LOCK_H_
#define _LOCK_H_

#include "Mutex.h"

class
Lock
{

public
:
// Acquire the state of the semaphore
Lock ( Mutex & mutex )
:
_mutex(mutex)
{

_mutex.Acquire();
}

// Release the state of the semaphore
~Lock ()
{

_mutex.Release();
}

private
:
Mutex & _mutex;
};


#endif



Mutex.h

//Example from http://www.relisoft.com/Win32/active.html
#if !defined _MUTEX_H_
#define _MUTEX_H_

class
Mutex
{

friend class
Lock;
public
:
Mutex () { InitializeCriticalSection (& _critSection); }
~
Mutex () { DeleteCriticalSection (& _critSection); }
private
:
void
Acquire ()
{

EnterCriticalSection (& _critSection);
}

void
Release ()
{

LeaveCriticalSection (& _critSection);
}


CRITICAL_SECTION _critSection;
};


#endif



Singleton.h

#include "Lock.h"
#include "Mutex.h"

class
aSingletonClass
{

public
:
//method to get Instance of class
static aSingletonClass *getInstance( void )
{

//Note that the class is only created when this method is called first time
if(!instance_)
instance_ = new aSingletonClass;
return
instance_;
}

//method to delete Instance of class
static void deleteInstance( void )
{

if
(instance_)
delete
instance_;
instance_ = NULL; //important as this can create dead reference problems
}
void
printSomething(char *name, int count)
{

Lock guard(mutex_);
std::cout << name << " loop " << count << std::endl;
}


private
:
//variable to store the instance of singleton
static aSingletonClass *instance_;
//default constructor should be private to prevent instantiation
aSingletonClass() {};
//destructor should be made private so no one can delete this accidently
~aSingletonClass() {};
//We also need to prevent copy being created of the object
aSingletonClass(const aSingletonClass&);

Mutex mutex_;
};



Thread.cpp

//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//This shows example of Multithreading, thread sync, Mutex
#include <windows.h>
#include <process.h>
#include <iostream>
#include "Singleton.h"

using namespace
std;

aSingletonClass* aSingletonClass::instance_ = NULL;

void
Func1(void *);
void
Func2(void *);

int
main()
{

HANDLE hThreads[2];

aSingletonClass *someVar = NULL;
//Create Instance
someVar = aSingletonClass::getInstance();

//Create two threads and start them
hThreads[0] = (HANDLE)_beginthread(Func1, 0, NULL);
hThreads[1] = (HANDLE)_beginthread(Func2, 0, NULL);

//Makes sure that both the threads have finished before going further
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);

cout << "Main exit" << endl;
return
0;
}


void
Func1(void *P)
{

int
Count;

for
(Count = 1; Count < 11; Count++)
{

aSingletonClass::getInstance()->printSomething("Func1", Count);
}

return
;
}


void
Func2(void *P)
{

int
Count;

for
(Count = 10; Count > 0; Count--)
{

aSingletonClass::getInstance()->printSomething("Func2", Count);
}

return
;
}





The Output is as follows:
Image

Wednesday, 11 March 2009

Multi-threading with Thread Synchronisation

Here is an example explaining the concept of multiple threads and their synchronisation:


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Example from http://www.adrianxw.dk/SoftwareSite/Threads/Threads2.html
//This shows an example of Multithreading and thread synchronisation
#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;

void
Func1(void *);
void
Func2(void *);

CRITICAL_SECTION Section; //This will act as Mutex


int
main()
{

HANDLE hThreads[2];
InitializeCriticalSection(&Section);

//Create two threads and start them
hThreads[0] = (HANDLE)_beginthread(Func1, 0, NULL);
hThreads[1] = (HANDLE)_beginthread(Func2, 0, NULL);

//Makes sure that both the threads have finished before going further
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);

//This is done after all threads have finished processing
DeleteCriticalSection(&Section);

cout << "Main exit" << endl;
return
0;
}


void
Func1(void *P)
{

int
Count;

for
(Count = 1; Count < 11; Count++)
{

EnterCriticalSection(&Section);
cout << "Func1 loop " << Count << endl;
LeaveCriticalSection(&Section);
}

return
;
}


void
Func2(void *P)
{

int
Count;

for
(Count = 10; Count > 0; Count--)
{

EnterCriticalSection(&Section);
cout << "Func2 loop " << Count << endl;
LeaveCriticalSection(&Section);
}

return
;
}





The output is as follows:
Image Complete explanation of the above program is available here.