Boost是否支持Windows EnterCriticalSection API

Does Boost have support for Windows EnterCriticalSection API?

本文关键字:EnterCriticalSection API Windows 支持 是否 Boost      更新时间:2023-10-16

我知道Boost支持互斥和lock_guard,它们可以用来实现关键部分。

但是Windows对于关键部分有一个特殊的API(请参见EnterCriticalSection和LeaveCriticalSection),它比互斥对象快很多(对于很少争用的短代码部分)。

因此,我的问题是——在Boost中是否有可能利用这个API,并在其他平台上回退到基于spinlock/mmutex/futex-的实现?

简单的答案是否定的。

以下是来自旧邮件列表线程的一些相关背景:

顺便说一句。我同意互斥是中更通用的解决方案

从性能角度来看。但公平地说,CS在简单设计我认为支持他们的可能性应该在最小的考虑在内。

这是有人给我指的那篇文章。结论是CS只有在以下情况下才会更快:

  • 进程中总共有不到8个线程
  • 你没有在后台跑步
  • 你不是在一台双处理器机器上

对我来说,这意味着简单的测试可以产生良好的CS性能结果,但任何现实世界的节目都会有一个完整的互斥。

我并不反对支持CS实现。然而,我最初选择不这样做的原因如下:

  • 使用PIMPL可以获得构建和破坏命中率习语,否则您必须在Boost.Threads标头中包含Windows.h,这是我根本不想做的。(这可以通过模拟MSDN中的CS ala OPTEX。)
  • 根据这篇研究论文,大多数程序不会从中受益CS设计
  • 编写一个(不可移植的)critical_section类如果你真的能利用Mutex模型的话

现在,我认为我做出了正确的选择,尽管我们可以更改实现以使用关键部分或OPTEX。

Bill Kempf

作为一个帮助维护Boost.Thread的人,以及一个未能将事件对象添加到Boost.Tthread中的人,我认为关键部分从未添加过,也不会添加到Boost中,原因如下:

  1. Win32关键部分使用boost::atomic和boost::condition_variable非常容易构建,因此不值得拥有官方版本。这可能是你能想象到的最复杂的一个,但非常可配置,包括constexpr就绪(不要问!):https://github.com/ned14/boost.outcome/blob/master/include/boost/outcome/v1/spinlock.hpp#L331

    您可以简单地通过匹配(基本)可锁定概念并使用原子compare_exchange(非x86/x64)或原子交换(x86/664)来构建自己的概念,然后在关键部分使用lock_guard来获取它。

    有些人可能会反对win32关键部分不是这样的。恐怕是这样的:它只是在原子上旋转一个旋转计数,然后懒洋洋地试图分配一个win32事件对象,然后等待它。没什么特别的。

  2. 尽管你可能认为关键部分(真正的用户模式互斥)更好/更快/其他什么,但它们可能并不像你想象的那么好。boost::mutex在Windows上是一个巨大而重量级的东西,它在内部使用win32信号量作为内核等待对象,因为需要模拟线程取消并在通用上下文中表现良好。对于某些单一用例来说,编写一个比另一个更快的并发结构是很容易的,但编写一个包含以下内容的并发结构却非常困难:

    1. 在无争议的情况下,比标准实施更快
    2. 在轻度争论的情况下,比标准实现更快
    3. 在竞争激烈的情况下,比标准实施更快

    即使你做到了以上三点,这仍然不够:你还需要对最坏情况下的进度顺序做出一些保证,这样锁定、等待和解锁的某些模式是否会产生可预测的结果。这就是为什么线程设施在狭窄的用例场景中看起来很慢,所以Boost.Thread就像STL一样,在非受控用例中看起来比手动锁定代码慢得多。

  3. 线程已经在用户模式下做了大量工作,以避免在Windows上进入内核睡眠。在POSIX上,任何主要的pthread实现也做了大量的工作来避免内核休眠,因此Boost.Thread不会复制这项工作。换句话说,关键部分在扩展到负载行为方面并没有给你带来任何好处,尽管不可避免地会有Boost。线程v4(尤其是在Windows上)做了大量的工作,而天真的实现却没有(Boost.Thread的计划重写在Windows上要高效得多,因为它可以假设Windows Vista或更高版本)。

因此,看起来默认的Boost互斥对象不支持它,但asio::detail::mutex支持它。

所以我最终使用了

#include <boost/asio/detail/mutex.hpp>
#include <boost/thread.hpp>
using boost::asio::detail::mutex;
using boost::lock_guard;
int myFunc()
{
  static mutex mtx;
  lock_guard<mutex> lock(mtx);
  . . .
}
相关文章:
  • 没有找到相关文章