Thread Synchronization : Using Critical Section

Download source code for this project from here Using Critical Section

Software development is a team effort. Unless team members cooperate with one another, synchronize their work with the rest of the team, the team can’t go far. Similarly if in a program there are several threads running, unless their activities are synchronized with one another the disaster is not far away. Windows supports four types of objects—Critical sections, Mutexes, Events and Semaphores—that can help us to coordinate the activities of concurrently running threads in an application. Of these Critical section is the simplest to use. If the resources like variables, structures, linked lists, etc. are shared by two or more threads, critical section can serialize the accesses to these resources. However, the resources must belong to the same process as critical section does not work across the processes.

If a thread needs exclusive access to a resource then it can lock and unlock the same. The resource in such a case is referred to as a ‘critical section’. If thread B tries to lock a critical section that is locked by thread A, then thread B is denied an access to the critical section until thread A unlocks it.

Let us now see an example of critical section where names of students are stored in a CStringList object. A thread sortthread sorts the names while another thread addthread adds a new name to the list. We have blocked the thread that adds the name to the list if the sorting thread is in progress. Also, we have blocked the thread that sorts the names if addition of names is in progress.

Create a dialog based application called ‘critical’. Add two buttons, an edit box and a list box to the dialog. The controls, their IDs and variables associated with them are given below:

Control ID Variable Category
Add button IDC_ADD
Sort button IDC_SORT
Edit box IDC_ADDEDIT m_addedit Value
List box IDC_SORTLIST m_sortlist Control

The dialog template after adding the controls would appear as shown below.

Image1

The name entered by the user in the edit box will get added to the string list if ‘Add’ button is clicked. The list box will show the sorted records if ‘Sort’ button is clicked.

Declare a global structure in ‘criticalDlg.h’ file as given below:

struct THREADPARAMS

{

CString itemstr ;

CListBox *list ;

CCriticalSection *cr ;

} ;

#include ‘afxmt.h’ file in ‘criticalDlg.h’ file. This makes the CCriticalSection class available to our application. Add a private variable m_c of type CCriticalSection in CCriticalDlg class. Also add a static variable m_strlist of type CStringList to the CCriticalDlg class. Add the following statement in ‘criticalDlg.cpp’.

CListBox CCriticalDlg::m_sortlist ;

Add the following code in OnInitDialog( ) function.

BOOL CCriticalDlg::OnInitDialog( )

{

// Code added by AppWizard

CStdioFile f ;

CString str ;

if ( f.Open ( “data.txt”, CFile::modeReadWrite ) != 0 )

{

while ( f.ReadString ( str ) != NULL )

m_strlist.AddTail ( str ) ;

}

f.Close( ) ;

return TRUE ;

}

The ‘data.txt’ file contains the names of students. Here, we have read the records from the file using CStdioFile::ReadString( ) function and added them to the string list using CStringList::AddTail( ) function.

Add OnSort( ) handler for the ‘Sort’ button. The code of OnSort( ) function is given below:

void CCriticalDlg::OnSort( )

{

THREADPARAMS *th = new THREADPARAMS ;

th -> itemstr = “” ;

th -> list = &m_sortlist ;

th -> cr = &m_c ;

AfxBeginThread ( sortthread, ( LPVOID ) th ) ;

}

Here we have initialised the elements of THREADPARAMS structure that we are passing to the sortthread( ) function. We have started the thread by calling AfxBeginThread( ) function. The code of the sortthread( ) function is given below:

UINT sortthread ( LPVOID param )

{

THREADPARAMS *th = ( THREADPARAMS* ) param ;

int i, j ;

CString l1, l2 ;

POSITION p1, p2 ;

th -> cr -> Lock( ) ;

int count = CCriticalDlg::m_strlist.GetCount( ) ;

for ( j = 0 ; j < count ; j++ )

{

p1 = CCriticalDlg::m_strlist.GetHeadPosition( ) ;

for ( i = 0 ; i < count – 1 ; i++ )

{

p2 = p1 ;

l1 = CCriticalDlg::m_strlist.GetNext ( p1 ) ;

l2 = CCriticalDlg::m_strlist.GetAt ( p1 ) ;

if ( l1 > l2 )

{

CCriticalDlg::m_strlist.SetAt ( p2, l2 ) ;

CCriticalDlg::m_strlist.SetAt ( p1, l1 ) ;

}

}

}

th -> list -> ResetContent( ) ;

POSITION pos = CCriticalDlg::m_strlist.GetHeadPosition( ) ;

for ( i = 0 ; i < count ; i++ )

th -> list -> AddString ( CCriticalDlg::m_strlist.GetNext ( pos ) ) ;

th -> cr -> Unlock( ) ;

return 0 ;

}

Here, we have first locked the object of CStringList class using CCriticalSection::Lock( ) function. Next we have sorted the list using the usual ‘bubble sort’ sorting logic. CStringList::GetNext( ) function gives the string at the specified position and sets the POSITION variable to point to the next entry. CStringList::GetNext( ) function gets the string at the given position. The sorted list is then displayed in the list box. After the thread is through with its job the object is unlocked using CCriticalSection::Unlock( ) function.

Add OnAdd( ) handler for the Add button and write the following code in it.

void CCriticalDlg::OnAdd( )

{

UpdateData ( TRUE ) ;

THREADPARAMS *th = new THREADPARAMS ;

th -> itemstr = m_addstr ;

th -> cr = &m_c ;

AfxBeginThread ( addthread, ( LPVOID ) th ) ;

}

UpdateData( TRUE ) transfers the name from edit box to m_addstr variable. We have initialised the THREADPARAMS structure with values that we intend to pass to the addthread( ) function. Next, we have started the thread by calling AfxBeginThread( ) function.

The code of the addthread( ) function is given below:

UINT addthread ( LPVOID param )

{

THREADPARAMS *th = ( THREADPARAMS* ) param ;

th -> cr -> Lock( ) ;

if ( !th -> itemstr.IsEmpty( ) )

CCriticalDlg::m_strlist.AddTail ( th -> itemstr ) ;

th -> cr -> Unlock( ) ;

return 0;

}

In this function, the critical section, i.e., m_strlist is locked using CCriticalSection::Lock( ). Now no other thread can use this object unless this thread unlocks it by calling CCriticalSection::UnLock( ) function.

Don’t forget to declare the thread functions in ‘criticalDlg.cpp’ as given below:

UINT addthread ( LPVOID param ) ;

UINT sortthread ( LPVOID param ) ;

Finally, add the OnOK( ) handler to write back the updated string list to the file. Its code is given below:

void CCriticalDlg::OnOK( )

{

CFile::Remove ( “data.txt” ) ;

CStdioFile f ;

if ( f.Open ( “data.txt”, CFile::modeCreate | CFile::modeReadWrite ) != 0 )

{

POSITION pos = m_strlist.GetHeadPosition( ) ;

CString str ;

for ( int i = 0 ; i < m_strlist.GetCount( ) ; i++ )

{

str = m_strlist.GetNext ( pos ) ;

f.WriteString ( str ) ;

f.WriteString ( “\n” ) ;

}

}

f.Close( ) ;

CDialog::OnOK( ) ;

}

Now run the program. If you click the ‘Sort’ button and immediately follow it by clicking the Add button the add thread would get blocked until the sort thread unlocks the critical section.

Download source code for this project from here Using Critical Section

This entry was posted in MFC, Tutorial and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>