C++ Logo

std-proposals

Advanced search

Slim mutexes and locks based on C++20 std::atomic::wait

From: Marko Mäkelä <marko.makela_at_[hidden]>
Date: Fri, 20 Aug 2021 08:45:09 +0300
Hi all,

For a database kernel, I needed a small mutex or rw-lock with minimal
features: no tracking of ownership, no reentrancy a.k.a. recursion for
the basic variant. The small size of the object (32 or 64 bits) allows
millions of the simplest mutex or rw-lock to be instantiated. One use
case is that a hash array contains a lock and a number of pointers in a
single cache line, such that the lock will protect the data that is
stored in that cache line.

I created a GitHub repository to demonstrate this:

https://github.com/dr-m/atomic_sync

I believe that the code works wherever std::atomic::wait() is available
(currently, this includes MSVC on Windows, GCC or Clang on Linux with
libstdc++-11). There is also a fallback implementation for C++11, using
futex system calls on Linux or OpenBSD.

I believe that it would be useful if the C++ standard library included
mutex or rw-lock primitives that build upon std::atomic. I would
appreciate feedback and advice how this could be converted into a formal
proposal for inclusion in the standard.

Similar C++11 code is "in production" already. On Microsoft Windows,
that implementation deviates from the above by using SRWLOCK,
WaitOnAddress() and WakeByAddressSingle().

FAQ: Why not std::mutex or std::shared_mutex?

The std::mutex or std::shared_mutex do have their place, and they work
well with debuggers and other tools. For special use cases, such as
block descriptors in a database buffer pool, small storage size and
minimal implementation overhead are more important.

Native mutexes or rw-locks tend to have huge storage requirements
(sizeof(pthread_mutex_t)==48 on 64-bit GNU/Linux) and may have
unsuitable semantics: When a lock is acquired by Thread A and ownership
is passed an unspecified thread (for example, one that will be invoked
on asynchronous I/O completion), we would want a subsequent acquisition
by Thread A to block until the lock has been released (by some other
thread). In pthread_mutex_t, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP can
be used to enable recursion, but there does not appear to be a portable
way to disable it.

With best regards,

        Marko Mäkelä

Received on 2021-08-20 00:45:19