custom RAII C++ implementation for scoped mutex locks
Asked Answered
C

1

13

I cannot use boost or the latest std::thread library. The way to go is to create a custom implementation of a scoped mutex.

In a few words when a class instance is create a mutex locks. Upon class destruction the mutex is unlocked.

Any implementation available? I don't want to re-invent the wheel.

I need to use pthreads.

  • resource acquisition is initialization == “RAII”
Carvelbuilt answered 2/11, 2011 at 7:59 Comment(0)
T
15

Note This is an old answer. C++11 contains better helpers that are more platform independent:

And other options like std::unique_lock, boost::unique_lock

Any RAII tutorial will do.

Here's the gist: (also on http://ideone.com/kkB86)

// stub mutex_t: implement this for your operating system
struct mutex_t 
{ 
    void Acquire() {} 
    void Release() {} 
};

struct LockGuard
{
     LockGuard(mutex_t& mutex) : _ref(mutex) 
     { 
         _ref.Acquire();  // TODO operating system specific
     }

     ~LockGuard() 
     { 
          _ref.Release(); // TODO operating system specific
     }
   private:
     LockGuard(const LockGuard&); // or use c++0x ` = delete`

     mutex_t& _ref;
};

int main()
{
    mutex_t mtx;

    {
        LockGuard lock(mtx);
        // LockGuard copy(lock); // ERROR: constructor private
        // lock = LockGuard(mtx);// ERROR: no default assignment operator
    }

}

Of course you can make it generic towards mutex_t, you could prevent subclassing. Copying/assignment is already prohibited because of the reference field

EDIT For pthreads:

struct mutex_t
{
    public:
        mutex_t(pthread_mutex_t &lock) : m_mutex(lock) {}

        void Acquire() { pthread_mutex_lock(&m_mutex);   }
        void Release() { pthread_mutex_unlock(&m_mutex); }
    private:
        pthread_mutex_t& m_mutex;
};
Tamasha answered 2/11, 2011 at 8:1 Comment(8)
I updated my question to request pthreads. Therefor your _ref.Acquire() will be pthread_mutex_lock(_ref)?Carvelbuilt
Mmm. the part to implement for your threading library was marked as such. Anyways, I added a quick implementation for pthread_mutex_t for reference.Tamasha
You had your answer even before I specify the OS details :-)Carvelbuilt
I'd advise against putting the pthread_mutex_lock directly into the lockguard. I'd prefer to have one correct RIAA class that can monitor many different synchronisation primitives. It reduces code duplication, makes LockGuard unit-testable, doesn't require you to recompile all if you change the lock implementation etc.Tamasha
note that you'll really want to check the return values because it is your primary defense when detecting threading errors. as well, pthread_mutex_trylock will be useful in a more thorough design.Theologize
We need pthread_mutex_init and pthread_mutex_destroy in Acquire and Release, don't we?Carvelbuilt
You could go that way if you want. But then, you'd really be inventing the wheel :). I guess there is nothing wrong with that - PoCo does it, Boost does it, the C++11 standard library does it!Tamasha
@cateof: You most probably want to initialize and destroy the mutex only once, even if you want to lock/unlock many times. Initialization and destruction are more related to the mutex_t construction and destruction (if you wish, but then you probably don't want to take the mutex by reference, but rather construct it internally)... At any rate that part of the problem should not be mixed with RAII over the lock.Honna

© 2022 - 2024 — McMap. All rights reserved.