Bernard
Bernard

Reputation: 5676

How is std::mutex's constexpr constructor implemented?

While looking at the C++ Reference for std::mutex, I noticed that the constructor for std::mutex is marked constexpr.

This is surprising at first, since we usually have to make a system call (either pthread_mutex_init() (POSIX) or CreateMutex() (Windows)) to initialize a mutex. However, on closer inspection, for POSIX, one can use the constant PTHREAD_MUTEX_INITIALIZER to statically initialize the mutex (perhaps as a global variable), though I can find no equivalent for Windows.

However, even if this static initialization for POSIX was the reason behind the constexpr constructor, there're still various unsolved issues for an implementation:

  1. On Windows (and perhaps other non-POSIX systems), there may not be a way to statically initialize mutexes.
  2. It was impossible to have different code paths depending on whether the constructor is being called at compilation time until C++20's std::is_constant_evaluated() was added, so we don't have a way to determine if PTHREAD_MUTEX_INITIALIZER or pthread_mutex_init() should be used.

So, how does one implement the constexpr constructor for std::mutex?

Upvotes: 6

Views: 1203

Answers (1)

Alex Guteniev
Alex Guteniev

Reputation: 13689

On Windows, it is possible to implement std::mutex as constexpr using SRWLOCK.

Unfortunately full SRWLOCK is available starting in Windows 7. It was introduced in Windows Vista, but without the ability to implement try_lock using it.

Visual Studio 2022 has dropped Windows Vista support, so it could have switched to SRWLOCK, but for ABI compatibility reasons, to be compatible down to VS 2015, it still uses the implementation that allowed runtime selection of sync primitive, to avoid SRWLOCK on pre-Win7.

Technically it is possible to implement std::mutex based on CreateEvent and lazy initialization, in Windows 95 and later, but this implementation would be complex and suboptimal, as it will not use the OS primitives directly and will not allow the OS to be aware of the mutex.


On POSIX, you can use PTHREAD_MUTEX_INITIALIZER unconditionally, even in runtime.

Upvotes: 2

Related Questions