3

这个问题之后,我想知道我们应该采取什么推荐方法来替换遗留代码中非常常见的模式。

我们有很多地方,主线程正在生成一个或多个后台工作线程,并使用适当同步的队列定期抽出一些工作让他们去做。因此,工作线程的一般模式如下所示:

会有一个事件HANDLE并在bool某处定义(通常作为成员变量) -

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

然后工作线程函数在工作之前等待事件发出信号,但会检查主循环内的终止请求 -

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;
}

然后主线程可以像这样给后台线程一些工作 -

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

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

它最终可以像这样终止工作线程 -

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

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

在某些情况下,我们使用了两个事件(一个用于工作,一个用于终止)WaitForMultipleObjects,但一般模式是相同的。

所以,看看用volatile boolC++11 标准等效替换,是不是就像替换这个一样简单

volatile bool bEndThread = false;

有了这个?

std::atomic<bool> bEndThread = false;

我确信它会起作用,但似乎还不够。此外,它不会影响我们使用两个事件和 no 的情况bool

请注意,我不打算用PPL和/或并发运行时等价物替换所有这些遗留的东西,因为虽然我们将它们用于新的开发,但遗留的代码库已经结束,只需要与最新的开发兼容工具(我上面链接的原始问题显示了我担心的地方)。

有人可以给我一个粗略的 C++11 标准代码示例,我们可以将其用于这种简单的线程管理模式来重写我们的遗留代码而无需过多重构?

4

1 回答 1

1

如果它没有损坏,请不要修复它(特别是如果这是一个遗留代码库)

  1. VS 风格的 volatile 还会存在几年。鉴于 MFC 没有死,这不会很快死。粗略的 Google 搜索显示您可以使用/volatile:ms.

  2. Atomics 可能会完成 volatile 的工作,特别是如果这是一个计数器,则性能开销可能很小。

  3. 与其 C++11 实现相比,许多 Windows 本机函数具有不同的性能特征。例如,Windows TimerQueues 和 Multimedia 具有 C++11 无法达到的精度。

    例如::sleep_for(5) 将睡 15 (而不是 5 或 6)。这可以通过一个神秘的调用来解决timeSetPeriod。另一个例子是对条件变量的解锁可能响应缓慢。修复这些问题的接口不会暴露给 Windows 上的 C++11。

于 2013-05-03T07:47:32.343 回答