为什么 sleep_for 调用 FreeLibrary? [英] Why sleep_for calls FreeLibrary?

查看:25
本文介绍了为什么 sleep_for 调用 FreeLibrary?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很震惊地跟踪这个简单的代码:

I'm shocked to trace this simple code:

#include <thread>

void foo()
{
    for (int i = 0; i < 1000000; ++i) {
        std::this_thread::sleep_for(std::chrono::nanoseconds(1));
    }
}

int main()
{
    std::thread t(foo);
    t.join();
}

你猜怎么着?sleep_for 每次都调用 FreeLibrary !

Guess what ? sleep_for calls FreeLibrary everytime !

kernel32.dll!_FreeLibraryStub@4()
msvcr120d.dll!Concurrency::details::DeleteAsyncTimerAndUnloadLibrary(_TP_TIMER * timer) Line 707
msvcr120d.dll!Concurrency::details::_Timer::_Stop() Line 111
msvcr120d.dll!Concurrency::details::_Timer::~_Timer() Line 100
msvcr120d.dll!`Concurrency::wait'::`7'::TimerObj::~TimerObj()
msvcr120d.dll!Concurrency::wait(unsigned int milliseconds) Line 155
test826.exe!std::this_thread::sleep_until(const xtime * _Abs_time) Line 137
test826.exe!std::this_thread::sleep_for<__int64,std::ratio<1,1000000000> >(const std::chrono::duration<__int64,std::ratio<1,1000000000> > & _Rel_time) Line 162
test826.exe!foo() Line 6

为什么 sleep_for 必须调用 FreeLibrary ?

Why sleep_for had to call FreeLibrary ?

这个程序使用 boost 库需要 2 秒,使用 msvcrt(发布模式)需要 3 分钟以上(失去耐心).我无法想象.

This program will take 2 seconds with boost library, and will take > 3 minutes (lose my patience) with msvcrt (Release mode). I can't imagine.

推荐答案

在 Visual C++ 2013 中,大多数 C++ 标准库并发功能位于 并发运行时 (ConcRT).ConcRT 是一个工作窃取运行时,提供协作调度和阻塞.

In Visual C++ 2013, most of the C++ Standard Library concurrency functionality sits atop the Concurrency Runtime (ConcRT). ConcRT is a work-stealing runtime that provides cooperative scheduling and blocking.

这里,Concurrency::wait 使用线程池计时器来执行等待.它使用 LoadLibrary/FreeLibrary 来增加承载 ConcRT 运行时的模块的引用计数,直到计时器挂起.这可确保在等待期间不会卸载模块.

Here, Concurrency::wait uses a thread pool timer to perform the wait. It uses LoadLibrary/FreeLibrary to increment the reference count of the module in which the ConcRT runtime is hosted for the duration that the timer is pending. This ensures that the module is not unloaded during the wait.

我不是 ConcRT 专家(甚至不是专家),所以我不能 100% 确定可以在此处卸载 ConcRT 模块的确切场景是什么.我确实知道我们对 std::thread_beginthreadex 进行了类似的更改,以获取对承载线程回调的模块的引用,以确保模块线程执行时未卸载.

I'm not a ConcRT expert (not even close), so I'm not 100% sure what is the exact scenario where the ConcRT module could be unloaded here. I do know that we made similar changes to std::thread and _beginthreadex, to acquire a reference to the module in which the thread callback is hosted, to ensure that the module is not unloaded while the thread is executing.

在 Visual C++ 2015 中,C++ 标准库并发功能被修改为直接位于 Windows 操作系统原语(例如 CreateThreadSleep 等)之上,而不是 ConcRT.这样做是为了提高性能,解决将 C++ 线程功能与操作系统功能混合使用时的正确性问题,并作为对 ConcRT 的更普遍的淡化的一部分.

In Visual C++ 2015, the C++ Standard Library concurrency functionality was modified to sit directly atop Windows operating system primitives (e.g. CreateThread, Sleep, etc.) instead of ConcRT. This was done to improve performance, to resolve correctness issues when mixing use of C++ threading functionality with use of operating system functionality, and as part of a more general deemphasization of ConcRT.

请注意,在 Windows 上,睡眠精度以毫秒为单位,零毫秒的睡眠通常意味着在回到我身边之前先做其他有用的工作".如果您使用 Visual C++ 2015 编译您的程序,每次调用 wait_for 都会依次调用 Sleep(0),这导致线程放弃其剩余时间片到任何其他准备运行的线程."

Note that on Windows, sleep precision is in milliseconds and a sleep of zero milliseconds generally means "go do other useful work before coming back to me." If you compile your program with Visual C++ 2015, each call to wait_for will in turn call Sleep(0), which "causes the thread to relinquish the remainder of its time slice to any other thread that is ready to run."

这篇关于为什么 sleep_for 调用 FreeLibrary?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆