简体   繁体   English

如何使用C ++ 11 atomics控制线程生命周期

[英]How to control thread lifetime using C++11 atomics

Following on from this question , I'd like to know what's the recommended approach we should take to replace the very common pattern we have in legacy code. 这个问题之后 ,我想知道我们应该采取什么建议的方法来替换遗留代码中的常见模式。

We have plenty of places where a primary thread is spawing one or more background worker threads and periodically pumping out some work for them to do, using a suitably synchronized queue. 我们有很多地方主要线程正在产生一个或多个后台工作线程,并使用适当同步的队列定期为他们做一些工作。 So the general pattern for a worker thread will look like this: 因此,工作线程的一般模式如下所示:

There will be an event HANDLE and a bool defined somewhere (usually as member variables) - 将会有一个事件HANDLE和一个bool定义在某处(通常作为成员变量) -

HANDLE hDoSomething = CreateEvent(NULL, FALSE, FALSE, NULL);
volatile bool bEndThread = false;

Then the worker thread function waits for the event to be signalled before doing work, but checks for a termination request inside the main loop - 然后工作线程函数在执行工作之前等待事件发出信号,但检查主循环内的终止请求 -

unsigned int ThreadFunc(void *pParam)
{
    // typical legacy implementation of a worker thread
    while (true)
    {
        // wait for event
        WaitForSingleObject(hDoSomething, INFINITE);

        // check for termination request
        if (bEndThread) break;

        // ... do background work ...
    }

    // normal termination
    return 0;
}

The primary thread can then give some work to the background thread like this - 然后,主线程可以为后台线程提供一些工作 - 如下所示 -

// ... put some work on a synchronized queue ...

// pulse worker thread to do the work
SetEvent(hDoSomething);

And it can finally terminate the worker thread like so - 它最终可以像这样终止工作线程 -

// to terminate the worker thread
bEndThread = true;
SetEvent(hDoSomething);

// wait for worker thread to die
WaitForSingleObject(hWorkerThreadHandle, dwSomeSuitableTimeOut);

In some cases, we've used two events (one for work, one for termination) and WaitForMultipleObjects instead, but the general pattern is the same. 在某些情况下,我们使用了两个事件(一个用于工作,一个用于终止)和WaitForMultipleObjects ,但是一般模式是相同的。

So, looking at replacing the volatile bool with a C++11 standard equivalent, is it as simple as replacing this 因此,考虑用C ++ 11标准等效替换volatile bool ,就像替换它一样简单

volatile bool bEndThread = false;

with this? 有了这个?

std::atomic<bool> bEndThread = false;

I'm sure it will work, but it doesn't seem enough. 我相信它会起作用,但似乎还不够。 Also, it doesn't affect the case where we use two events and no bool . 此外,它不会影响我们使用两个事件而不使用bool

Note, I'm not intending to replace all this legacy stuff with the PPL and/or Concurrency Runtime equivalents because although we use these for new development, the legacy codebase is end-of-life and just needs to be compatible with the latest development tools (the original question I linked above shows where my concern arose). 注意,我不打算用PPL和/或并发运行时等效替换所有这些遗留的东西,因为虽然我们将它们用于新开发,但遗留代码库已经过期,只需要与最新开发兼容工具(我上面链接的原始问题显示我的担忧出现在哪里)。

Can someone give me a rough example of C++11 standard code we could use for this simple thread management pattern to rewrite our legacy code without too much refactoring? 有人能给我一个粗略的C ++ 11标准代码示例,我们可以使用这个简单的线程管理模式来重写我们的遗留代码而不需要太多的重构吗?

If it ain't broken don't fix it (especially if this is a legacy code base) 如果它没有被破坏,请不要修复它(特别是如果这是遗留的代码库)

  1. VS style volatile will be around for a few more years. VS风格的波动将会持续几年。 Given that MFC isn't dead this won't be dead any time soon. 鉴于MFC尚未死亡,这种情况不会很快消失。 A cursory Google search says you can control it with /volatile:ms . 粗略的谷歌搜索说你可以使用/volatile:ms来控制它。

  2. Atomics might do the job of volatile, especially if this is a counter there might be little performance overhead. Atomics可能会执行volatile的工作,特别是如果这是一个计数器,可能会有很少的性能开销。

  3. Many Windows native functions have different performance characteristics when compared to their C++11 implementation. 与C ++ 11实现相比,许多Windows本机函数具有不同的性能特征。 For example, Windows TimerQueues and Multimedia have precision that is not possible to achieve with C++11. 例如,Windows TimerQueues和Multimedia具有使用C ++ 11无法实现的精度。

    For example ::sleep_for(5) will sleep for 15 (and not 5 or 6). 例如::sleep_for(5)将睡眠15(而不是5或6)。 This can be solved with a mysterious call to timeSetPeriod . 这可以通过对timeSetPeriod的神秘调用来timeSetPeriod Another example is that unlocking on a condition variable can be slow to respond. 另一个例子是,对条件变量进行解锁可能会很慢。 Interfaces to fix these aren't exposed to C++11 on Windows. 修复这些的接口不会在Windows上暴露给C ++ 11。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM