std::mutex 的 constexpr 构造函数是如何实现的?

Ber*_*ard 5 c++ constructor mutex constexpr c++11

在查看 C++ Reference for 时std::mutex,我注意到 for 的构造函数std::mutex被标记为constexpr

起初这令人惊讶,因为我们通常必须进行系统调用(pthread_mutex_init()(POSIX)或CreateMutex()(Windows))来初始化互斥体。然而,经过仔细检查,对于 POSIX,可以使用常量静态PTHREAD_MUTEX_INITIALIZER初始化互斥体(可能作为全局变量),尽管我找不到 Windows 的等效项。

然而,即使 POSIX 的静态初始化是constexpr构造函数背后的原因,但实现中仍然存在各种未解决的问题:

  1. 在 Windows(或许还有其他非 POSIX 系统)上,可能没有静态初始化互斥体的方法。
  2. 在添加C++20 之前,不可能根据编译时是否调用构造函数来拥有不同的代码路径std::is_constant_evaluated(),因此我们没有办法确定是否应该使用PTHREAD_MUTEX_INITIALIZER或。pthread_mutex_init()

那么,如何实现 的constexpr构造函数呢std::mutex

Ale*_*iev 2

在 Windows上,可以std::mutex使用.constexprSRWLOCK

不幸的是,完整功能SRWLOCK从 Windows 7 开始可用。它是在 Windows Vista 中引入的,但无法实现使用try_lock它。

Visual Studio 2022 已经放弃了 Windows Vista 支持,因此它本来可以切换到SRWLOCK,但出于 ABI 兼容性原因,为了向下兼容到 VS 2015,它仍然使用允许运行时选择同步原语的实现,以避免SRWLOCK在 Win7 之前的版本上使用。

从技术上讲,可以在 Windows 95 及更高版本中实现std::mutex基于CreateEvent延迟初始化,但这种实现会很复杂且不是最佳的,因为它不会直接使用操作系统原语,也不会允许操作系统知道互斥体。


在 POSIX 上,您可以PTHREAD_MUTEX_INITIALIZER无条件使用,甚至在运行时也是如此。

  • Windows 没有。实现它的是MSVC。目前它不是 MSVC 中的 `constexpr`。随着新的 ABI 突破性版本的推出,它将通过“SRWLOCK”和“SRWLOCK_INIT”实现 (2认同)