3

我正在重写使用 WinAPI 进行线程化的代码,以使用新的标准线程库。

我想知道在 C++11 中注意到互斥体被遗弃或丢失的等效方法是什么。

以下代码必须将初始化过程“外包”给创建的线程,但在完成并知道初始化结果之前不应返回。

bool Foo::Example()
{
    m_thread = std::thread(&Foo::ThreadProc, this);

    // wait for event before waiting for mutex
    WaitForSingleObject(m_hEvent, INFINITE);
    ResetEvent(m_hEvent);

    // the thread aquired the mutex. now wait until it is released or abandoned
    DWORD ret = WaitForSingleObject(m_hMutex, INFINITE);
    ReleaseMutex(m_hMutex);

    // check the result
    if (ret == WAIT_ABANDONED)
        return false;
    return true;
}
void Foo::ThreadProc()
{
    // aquire mutex and signal that it's done
    WaitForSingleObject(m_hMutex, INFINITE);
    SetEvent(m_hEvent);

    // ... initialization (required to be in this thread)

    if (initializationfailure)
        return; // failure. mutex is abandoned

    // success. mutex is unlocked
    ReleaseMutex(m_hMutex);

    // ... do the work
}

WAIT_ABANDONED 检查的替代品是什么?我在 std::mutex 中没有找到任何东西。它甚至说The behavior is undefined if the mutex is not unlocked before being destroyed, i.e. some thread still owns it.没有等价物吗?std 线程库中的任何东西都接近这个?

我还接受改进代码的建议。对于这样一个简单的任务,似乎同步太多了。

4

1 回答 1

7

没有等价物。您可以使用 RAII 解锁互斥锁并避免首先放弃它,然后您就不需要对其进行测试。

您可以使用 future 而不是等待事件并使用互斥锁,这比容易出错的显式同步简单得多:

bool Foo::Example()
{
    std::promise<bool> p;
    auto res = p.get_future();
    m_thread = std::thread(&Foo::ThreadProc, this, std::ref(p));
    return res.get();
}
void Foo::ThreadProc(std::promise<bool>& p)
{
    // ... initialization (required to be in this thread)

    if (initializationfailure)
    {
        p.set_value(false); // failure.
        return;
    }

    p.set_value(true);

    // IMPORTANT: p is a dangling reference now!

    // ... do the work
}

主线程将阻塞直到 promise 被实现,然后根据初始化是否成功返回 true 或 false。

您可以通过制作它来避免悬空引用,ThreadProc(std::promise<bool> p)然后将其作为std::move(p)而不是传递,std::ref(p)但我认为std::threadVisual C++ 中的 不支持仅移动类型的完美转发。

于 2013-06-03T21:27:07.103 回答