我一直在尝试摆脱所有提升引用的项目,并切换到纯C++ 11。

一方面,创建了线程工作程序,这些线程工作程序等待发出“go”命令的障碍,进行工作(遍及N个线程),并在所有工作完成时进行同步。基本思想是主循环给出执行顺序(boost::barrier .wait()),并使用相同的函数等待结果。

我在另一个项目中实现了一个基于Boost版本的定制屏障,并且一切正常。实现如下:

Barrier.h:

class Barrier {
public:
    Barrier(unsigned int n);
    void Wait(void);
private:
    std::mutex counterMutex;
    std::mutex waitMutex;

    unsigned int expectedN;
    unsigned int currentN;
};

Barrier.cpp
Barrier::Barrier(unsigned int n) {
    expectedN = n;
    currentN = expectedN;
}

void Barrier::Wait(void) {
    counterMutex.lock();

    // If we're the first thread, we want an extra lock at our disposal

    if (currentN == expectedN) {
        waitMutex.lock();
    }

    // Decrease thread counter

    --currentN;

    if (currentN == 0) {
        currentN = expectedN;
        waitMutex.unlock();

        currentN = expectedN;
        counterMutex.unlock();
    } else {
        counterMutex.unlock();

        waitMutex.lock();
        waitMutex.unlock();
    }
}

该代码已在iOS和Android的NDK上使用,没有任何问题,但是在Visual Studio 2013项目上尝试使用此代码时,似乎只有锁定互斥锁的线程才能对其进行解锁(断言:解锁未拥有的互斥锁)。

我可以使用适用于C++ 11的任何非旋转(阻塞,例如这一步)障碍吗?我只能找到使用忙碌等待的障碍,这是我要防止的事情(除非确实没有理由)。

最佳答案

class Barrier {
public:
    explicit Barrier(std::size_t iCount) :
      mThreshold(iCount),
      mCount(iCount),
      mGeneration(0) {
    }

    void Wait() {
        std::unique_lock<std::mutex> lLock{mMutex};
        auto lGen = mGeneration;
        if (!--mCount) {
            mGeneration++;
            mCount = mThreshold;
            mCond.notify_all();
        } else {
            mCond.wait(lLock, [this, lGen] { return lGen != mGeneration; });
        }
    }

private:
    std::mutex mMutex;
    std::condition_variable mCond;
    std::size_t mThreshold;
    std::size_t mCount;
    std::size_t mGeneration;
};

关于multithreading - 在C++ 11中实现boost::barrier,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24465533/

10-09 05:44