Reputation: 3461
I have a socket shared between 4 threads and I wanted to use the RAII principle for acquiring and releasing the mutex.
The ground realities
The Background
Instead of having to lock the mutex for the socket everytime before using it, and then unlocking the mutex right afterwards, I thought I could write a scoped_lock()
which would lock the mutex, and once it goes out of scope, it would automatically unlock the mutex.
So, quite simply I do a lock in the constructor and an unlock in the destructor, as shown here.
ScopedLock::ScopedLock(pthread_mutex_t& mutex, int& errorCode)
: m_Mutex(mutex)
{
errorCode = m_lock();
}
ScopedLock::~ScopedLock()
{
errorCode = m_unlock();
}
where m_lock()
and m_unlock()
are quite simply two wrapper functions around the pthread_mutex_lock()
and the pthread_mutex_unlock()
functions respectively, with some additional tracelines/logging.
In this way, I would not have to write at least two unlock statements, one for the good case and one for the bad case (at least one, could be more bad-paths in some situations).
The Problem
The problem that I have bumped into and the thing that I don't like about this scheme is the destructor.
I have diligiently done for every function the error-handling, but from the destructor of this ScopedLock()
, I cannot inform the caller about any errors that might be returned my m_unlock()
.
Upvotes: 2
Views: 774
Reputation: 60117
This is a fundamental problem with RAII, but in this case, you're in luck. pthread_unlock
only fails if you set up the mutex wrong (EINVAL
) or if you're attempting to unlock an error checking mutex from a thread that doesn't own it (EPERM
). These errors are indications of bugs in your code, not runtime errors that you should be taking into account. assert
ing errorCode==0
is a reasonable strategy in this case.
Upvotes: 2