7

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?

12
  • 2
    On MSVC, the mutex constructor isn't constexpr yet it is implemented as (latest visual studio 2019, full C++20 support on, /Zc:__cplusplus ). /* constexpr */ mutex() noexcept // TRANSITION, ABI). The constructor (after 2 steps) calls into the runtime directly so I do think that indeed a CreateMutex is done there. I can think of an implementation with postponed creation of the actual OS mutex until the first lock (mutex can't be created in locked state), and maintaining the lock state using std::atomic<bool>. std::atomic also has a constexpr constructor, (last part is me brainstorming). Commented Aug 29, 2021 at 5:51
  • @PepijnKramer That sounds like a way to implement it, yes, but making it lazy just adds overhead for no benefit as far as I can see. That feels like an unneeded abstraction that kind of goes against C++'s design principles of giving control to the user as much as possible... Commented Aug 29, 2021 at 7:28
  • Anyway I don't know the real answer to your question :) From the standard: constexpr functions can only depend on functionality which is a constant expression. Being a constexpr function does not mean that the function is executed at compile time. It says, that the function has the potential to run at compile time. A constexpr function can also run a runtime Commented Aug 29, 2021 at 7:59
  • Yeah, but constexpr means that the function must be runnable at compile time, which rules out any kind of syscalls. (And if you're using std::is_constant_evaluated you still have to ensure that the constant evaluated branch is constexpr-safe.) Commented Aug 29, 2021 at 8:02
  • Good read :) stackoverflow.com/questions/23775705/… Commented Aug 29, 2021 at 8:12

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

So, how does Windows implement the std::mutex constructor?
Windows doesn't. It is MSVC that implements it. Currently it is not constexpr in MSVC. With the new ABI breaking release it will be though - with SRWLOCK and SRWLOCK_INIT
@AlexGuteniev it's neither Windows nor MSVC because the C++ stdlib is a separate thing and you can find the source code in github.com/microsoft/STL

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.