HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Recursive shared mutex

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
recursivemutexshared

Problem

I've been looking for an implementation of a recursive shared mutex to handle a very special data tree inside a heavy multi-threaded application.

Because boost and the stdlib does not have this special type, I wrote one myself. However, I am not sure if I missed something...

You find the full implementation with tests at github. Tested with GCC 5.4.

Features

  • Recursive for exclusive ownership with lock and lock_shared.



  • Recursive for sharable ownership with lock_shared.



  • Threads trying to get exclusive ownership have a higher priority then new threads trying to get sharable ownership.



  • Maximum waiting writers, level of ownerships: uint32::max



recursive_shared_mutex.hpp

```
/*
* Copyright (c) 2017 Toni Neubert, all rights reserved.
*/
#pragma once

#include
#include
#include
#include

class RecursiveSharedMutex {
public:
/**
* @brief Constructs the mutex.
*/
RecursiveSharedMutex();

/**
* @brief Locks the mutex for exclusive write access for this thread.
* Blocks execution as long as write access is not available:
other thread has write access
other threads try to get write access
other threads have read access
*
* A thread may call lock repeatedly.
* Ownership will only be released after the thread makes a matching number of calls to unlock.
*/
void lock();

/**
* @brief Locks the mutex for sharable read access.
* Blocks execution as long as read access is not available:
other thread has write access
other threads try to get write access
*
* A thread may call lock repeatedly.
* Ownership will only be released after the thread makes a matching number of calls to unlock_shared.
*/
void lock_shared();

/**
* @brief Unlocks the mutex for this thread if its level

Solution

One thought I had on this: wouldn't it play nicer if there was a thread yield outside the mutex in the tight for-loops? Or perhaps we scale up to that?

I've also been using this try_lock addition;

bool RecursiveSharedMutex::try_lock() {
    auto threadId = std::this_thread::get_id();
    std::thread::id emptyThreadId;
    std::lock_guard lock(_mtx);

    if (_writerThreadId == threadId) {
        ++_writersOwnership;
        return true;
    }

    if (_readersOwnership.size() == 0 && _writerThreadId.compare_exchange_weak(emptyThreadId, threadId))
        return true;

    return false;
}

Code Snippets

bool RecursiveSharedMutex::try_lock() {
    auto threadId = std::this_thread::get_id();
    std::thread::id emptyThreadId;
    std::lock_guard<std::mutex> lock(_mtx);

    if (_writerThreadId == threadId) {
        ++_writersOwnership;
        return true;
    }

    if (_readersOwnership.size() == 0 && _writerThreadId.compare_exchange_weak(emptyThreadId, threadId))
        return true;

    return false;
}

Context

StackExchange Code Review Q#161735, answer score: 2

Revisions (0)

No revisions yet.