Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does scope-locking work?

Tags:

c++

I'm learning C++ and I saw that the source-code for a scope lock is quite simple. . How does it work, and how is this an example of "Resource Acquisition is Instantiation" (RAII) ?

like image 678
Jasper Blues Avatar asked Jan 11 '13 10:01

Jasper Blues


People also ask

What is scope locking?

The Scoped Locking C++ idiom ensures that a lock is acquired when control enters a scope and the lock is released automatically when control leaves the scope. Also Known As. Synchronized Block, Object-Construction-is-Resource-Acquisition.

Are lock guards deprecated?

There exist valid use cases where it is desirable for scoped_lock to accept variadic template parameter packs which may be empty. And the empty case should not lock anything. And that's why lock_guard isn't deprecated.


2 Answers

The idea of RAII (Resource Acquisition Is Initialisation) is that creating an object and initialising it are joined together into one unseparable action. This generally means they're performed in the object's constructor.

Scoped locks work by locking a mutex when they are constructed, and unlocking it when they are destructed. The C++ rules guarantee that when control flow leaves a scope (even via an exception), objects local to the scope being exited are destructed correctly. This means using a scoped lock instead of manually calling lock() and unlock() makes it impossible to accidentally not unlock the mutex, e.g. when an exception is thrown in the middle of the code between lock() and unlock().

This principle applies to all scenarios of acquiring resources which have to be released, not just to locking mutexes. It's good practice to provide such "scope guard" classes for other operations with similar syntax.

For example, I recently worked on a data structure class which normally sends signals when it's modified, but these have to be disabled for some bulk operations. Providing a scope guard class which disables them at construction and re-enables them at destruction prevents potential unbalanced calls to the disable/enable functions.

like image 190
Angew is no longer proud of SO Avatar answered Nov 05 '22 06:11

Angew is no longer proud of SO


Here is the little code that illustrates scoped lock:

 void do_something()
 {
    //here in the constructor of scoped_lock, the mutex is locked, 
    //and a reference to it is kept in the object `lock` for future use
     scoped_lock lock(shared_mutex_obj);

    //here goes the critical section code

}//<---here : the object `lock` goes out of scope
 //that means, the destructor of scoped_lock will run.
 //in the destructor, the mutex is unlocked.

Read the comments. That explains how scoped_lock works.

And here is how scoped_lock is typically implemented (minimal code):

class scoped_lock : noncopyable
{
     mutex_impl &_mtx; //keep ref to the mutex passed to the constructor
   public:
      scoped_lock(mutex_impl & mtx ) : _mtx(mtx) 
      { 
          _mtx.lock();  //lock the mutex in the constructor
      }
      ~scoped_lock() 
      { 
         _mtx.unlock(); //unlock the mutex in the constructor
      }
};
like image 33
Nawaz Avatar answered Nov 05 '22 06:11

Nawaz