Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Hardwired's Named Critical Section and Named Spin Lock

0.00/5 (No votes)
23 Feb 2005 2  
Named critical section and named spin lock - you may find it useful for debugging complex applications.

Introduction

Working with critical section is not quite an easy task. Of course, if you have just two threads and one critical section, it's alright. But if you have about 10 threads, and you have to synchronize the use of about 20-30 variables then you will probably have problems. A very useful tool used is ProcessExplorer from Sysinternals. But it doesn't tell you a lot about the Critical Section object. So, I needed a way to trace all the critical sections, when they get locked/unlocked, and by whom. That is all about it.

Using the code

To use these classes, you got to have the basics about CCriticalSection and CSingleLock. If you don't, come back when you read all about it from MSDN. This works both for /DEBUG mode and /RELEASE mode. But only in /DEBUG mode you'll be able to trace all the Critical Section "activity". In /RELEASE mode you will not get any debug messages. Still, if you wish to see them, then edit debugtrace.cpp and debugtrace.h files and remove all the #ifndef and #endif lines.

First add debugtrace.h, debugtrace.cpp, spinlock.h, spinlock.cpp, namedcriticalsection.h and namedcriticalsection.cpp files to your project and of course #include "namedcriticalsection.h" where needed.

To use CNamedCriticalSection, it's very easy, just follow the following steps:

//

// MyClass.h

//

#include "namedcriticalsection.h"


class MyClass
{
    CNamedCriticalSection    Section;

public:
    MyClass();
    ~MyClass();

    void    SomeMethod(void);

    ...
};
//

// MyClass.cpp

//

#include "myclass.h"


MyClass::MyClass()
:    Section( "MyClass" )    // the critical section object should have 

                // the same name as the class, but you can

                // set it to whatever you want

{
    ...
}

MyClass::~MyClass()
{
    ...
}

//

// let's assume this gets executed only by one single thread

//

void MyClass::SomeMethod(void)
{
    CSpinLock        Spin( &Section, "MyClass::SomeMethod" );

    if( Spin.Lock() )
    {
        //

        // locked section; this is where you operate with

        // protected data

        //

        ...
        Spin.Unlock();
    }
}

OK. So, the class has a member function which locks the section and gets exclusive rights to operate with some data. We also assumed that the MyClass::SomeFunction() gets executed only by one single thread, let's say the main thread of the process.

Let's say that the application starts another thread which wants to use the same data as the one MyClass::SomeFunction() locks. This means that we have to wait for the critical section to get unlocked. Once it gets unlocked by the main thread, this new thread locks it. Please, also read the comments in the code sample below:

//

// Thread function - started with AfxThreadBegin(...), for example

//

UINT    SomeThread( LPVOID lParam )
{
    MyClass        *pmy = NULL;

    if( NULL == ( pmy = (MyClass*)lParam ) )
        return 0;

    //

    // create the spinlock

    // we'll use different name for spin, so we'll know that the section

    // is locked by the thread function

    //

    CSpinLock        Spin( &(pmy->Section), "SomeThread" );

    //

    // try to lock the section

    // this actualy waits infinitely till the other thread unlocks the section

    //

    if( Spin.Lock() )
    {
        //

        // locked section; this is where you operate with

        // protected data

        //

        ...

        //

        // finished, so let's unlock the section because the other

        // thread waits for it. If not, you'll probably get a deadlock!!!

        //

        Spin.Unlock();
    }

    ...
    return 1;
}

That's all! It's very simple (I think:)), but I am sure you'll find it useful. It made me find a lot of bugs.

One more thing: If your application already has a lot of source-code you might think that it is really hard to replace CCriticalSection with CNamedCriticalSection and CSingleLock with CSpinLocK. Well, it is not hard, it's quite simple actually. Just remember that CNamedCriticalSection and CSpinLock constructors need a name string.

Points of Interest

It's interesting:). Seriously, you will need this while coding large applications with a lot of threads.

History

  • Version 1.0 - 23rd- February-2005 - As promised in the CDebugTrace article, I have posted this one, too.

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