Aquarius_Girl
Aquarius_Girl

Reputation: 22906

Creating a mutex locker class in C++

This is what I have done so far:

class mutexLocker
{
    private:
    /* Declaration of a Mutex variable `mutexA`. */
    pthread_mutex_t &mutexA;

    /* `mutexStatus` holds the return value of the function`pthread_mutex_lock `. 
    This value has to be returned to the callee so we need to preserve it in a class
    variable. */
    int             mutexStatus;

    /* We need to decide how to deal with the situation when one thread tries to lock then
    mutex repeatedly. If the mutex is of type recursive, then there won't be any problem for 
    sure, but otherwise the case may result in a deadlock. */
    pthread_t       calleeThreadId;

    public:
    /* Constructor attempts to lock the desired mutex variable. */
    mutexLocker (pthread_mutex_t argMutexVariable, pthread_t threadId) 
    : mutexA (argMutexVariable, calleeThreadId)
    {
        /* Return value is needed in order to know whether the mutex has been 
        successfully locked or not. */
        int mutexStatus = pthread_mutex_lock (&argMutexVariable);
    }

    /* Since the constructor can't return anything, we need to have a separate function
    which returns the status of the lock. */
    int getMutexLockStatus ()
    {
        return mutexStatus;
    }

    /* The destructor will get called automatically whereever the callee's scope ends, and
    will get the mutex unlocked. */
    ~mutexLocker ()
    {
        pthread_mutex_unlock (&mutexA);
    }
};

What other functionalities should be provided in a DIY mutex locker class?

Upvotes: 3

Views: 2901

Answers (3)

justin
justin

Reputation: 104698

First, Graeme and Slavik81's answers are both really good (+1).

Now, as far as what to add:

  • you may want additional error support, depending how you handle errors. For example, if your team throws exceptions if the lock failed, the class could create and throw the exception.
  • as a diagnostic, you may want to verify the client tested that the acquisition succeeded (e.g. assert in the dtor if they never verified the lock succeeded).
  • you may want a 'retry' acquisition functionality. it's better to retry before throwing an exception, imo. Personally, I just consider it a programmer's error if EBUSY -- don't hold long locks!
  • also stash your pthread_mutex_t in a class - prohibit copying, assignment, and such. pass that to your locker.
  • some clients may want a simple method to test success, rather than evaluating the status. depends on how you use it.
  • do not unlock in the dtor if you did not acquire the lock
  • check the result of the unlock. determine error handling in this scenario.

perhaps more importantly - determine what to remove:

  • no copying. explicitly deleting the copy ctor expresses intent.
  • delete operator= -- expresses intent.
  • delete moves
  • calleeThreadId: remove unless you find useful. specifically, consider how you would actually implement this error detection you are proposing -- the locker seems to be the wrong place for the data, imo. i prefer to keep these lockers minimally small, focused, and simple.
  • extra mile: prevent heap allocations; e.g. delete primary variants of operator new/delete.
  • if you don't retry, then the status could be const.
  • threadID, if you decide to keep it, could also be const.

Finally, pass the mutex by reference in the (although i assume it is a typo).

Upvotes: 1

Graeme
Graeme

Reputation: 4592

I fully agree with Slavik81's comments about not creating functionality you don't have a use case for.

Nevertheless referencing the Boost implementations of lock classess may be a good starting point in terms of understanding common requirements of their interfaces: http://www.boost.org/doc/libs/1_42_0/doc/html/thread/synchronization.html#thread.synchronization.locks

In terms of the standard C++11 introduces std::lock_guard: http://en.cppreference.com/w/cpp/thread/lock_guard

Upvotes: 5

cgmb
cgmb

Reputation: 4414

You're approaching this a little backwards. You write code to solve problems you're facing. Don't write code to solve problems you don't have. "You aren't gonna need it" is a good principle.

No other functionalities should be provided unless you have a problem that could be solved with them. I assume you don't have such a problem, given that you haven't mentioned any. Thus, no other functionalities should be added yet.

Upvotes: 5

Related Questions