A C#-like lock class for C++
A very simple class that allows you to easily lock blocks of code from multi-threaded access.
Preamble
This is nothing earth-shattering, just a little trick I've picked up, and like because it is rather slick.
Update
Don't use this code unless you have to. As pointed out in the comments, STL already has this functionality. See std::mutex[^] and std::lock_guard[^].
Don't use this code unless you have to. As pointed out in the comments, STL already has this functionality. See std::mutex[^] and std::lock_guard[^].
Introduction
In C# we uselock
, without a second thought, to prevent simultaneous access from multiple threads. However in plan vanilla C++, you need to explicitly EnterCriticalSection
and LeaveCriticalSection
. Sometimes you may enter, but forget to leave. This tip takes care of that, and makes the code more compact.Usage
The code is used as shown below:// All Lock classes using this will be mutually exclusive static Section mySection; void SomeFunction() { // This block cannot be accessed simultaneously by multiple threads { Lock lock(mySection); // // any arbitrary code // } // end of locked block }Simple, isn't it? Basically what you do is, define a
Section
instance for each block of code that should be locked. This is usually a class member, but can easily be global too. Then wrap the portion of code to be locked in a block, and put a Lock
instance at the top of it, passing the Section
instance to it.If you want several blocks that need to be locked from multiple threads, but not from each other, create the same number of
Section
s and use them in each block.Code
These are the contents of lock.h, which contains the classesLock
and Section
.// Lock.h #pragma once #include <windows.h> class Lock; // Forward declaration // Class to encapsulate CRITICAL_SECTION class Section { // Actual critical section that will do the locking CRITICAL_SECTION criticalSection; public: // Constructor initializes critical section Section() { InitializeCriticalSection(&criticalSection); } // Destructor deletes critical section ~Section() { DeleteCriticalSection(&criticalSection); } private: friend Lock; // Allow Lock class to access Enter and Leave methods // Methods to enter and leave the critical section defined by the field above void Enter() { EnterCriticalSection(&criticalSection); } void Leave() { LeaveCriticalSection(&criticalSection); } }; // Class that does the locking class Lock { Section & section; // Section defined by user will be saved here public: // Constructor saves user defined critical section and enters it Lock(Section & s) : section(s) { section.Enter(); } // Destructor leaves critical section ~Lock() { section.Leave(); } };That's it, quite simple (but see the disclaimer).
How it works
So what happens here? You veterans will find it quite obvious, but I'll explain it as easily as possible for others who don't.First,
Section
just hides a regular CRITICAL_SECTION
. Why hide it? Just to prevent unwary maintainers of our code from messing with it. The constructor and destructor initialize and delete the CRITICAL_SECTION
respectively.The
Lock
class does the actual locking. When we create an auto variable of this type in the code block, the constructor is called and enters the critical section defined in the Section
passed to it. Leaving the scope of the block calls the destructor, which in turn calls LeaveCriticalSection
.Note that the
Section
field in Lock
is a reference - this is to prevent the former's constructor from being called again, causing a double initialization of the same CRITICAL_SECTION
.