CountDownLatch 等价物

7

对于一些并发编程,我可以使用Java的CountDownLatch概念。在C++11中是否有相应的概念,或者在C++中该概念应该被称为什么?

我想要的是当计数达到零时调用函数。

如果还没有,我会自己编写一个类,如下所示:

class countdown_function {
public:
  countdown_function( size_t count );
  countdown_function( const countdown_function& ) = default;
  countdown_function( countdown_function&& ) = default;
  countdown_function& operator=( const countdown_function& ) = default;
  countdown_function& operator=( countdown_function&& ) = default;
  // Callback to be invoked
  countdown_function& operator=(std::function<void()> callback);
  countdown_function& operator--();
private:
  struct internal {
    std::function<void()> _callback;
    size_t _count;
    // + some concurrent handling
  };
  // Make sure this class can be copied but still references
  // same state
  std::shared_ptr<internal> _state;
};

请问是否已经有类似的东西可用?

场景如下:

countdown_function counter( 2 );
counter = [success_callback]() {
  success_callback();
};

startTask1Async( [counter, somework]() {
  somework();
  --counter;
}, errorCallback );

startTask2Async( [counter, otherwork]() {
  otherwork();
  --counter;
}, errorCallback );

这个到底有什么用? - Xeo
我添加了一个使用示例。 - abergmeier
1
所以基本上你想要在所有异步任务都完成时执行回调吗?如果是的话,你可以直接滥用 shared_ptr 的释放器并丢弃手动减量。 - Xeo
如果代码真的那么简单,你确实是对的。我在示例中添加了另一个(error)回调,在这种情况下,我不希望调用success_callback。这就是我没有使用shared_ptr的删除器的原因。 - abergmeier
1
这个问题在下一个C++标准中有一个提案。作为gcl的一部分,已经有了实现。 - John Schug
@JohnSchug确实,在这里。你能否把它作为答案呈现出来? - abergmeier
2个回答

4
这个问题在下一个C++标准中有一个提案,可以参考这里。Google并发库也提供了相关的实现,可以参考这里

虽然gcl::countdown_latch'不是我真正想要的(因为它是一种阻止变量),但我认为你对标题问题的回答最好。我真的很想用--代替countDown`,但那只是我的个人喜好。 - abergmeier

2
我经常希望能够实现同样的事情。以下是一种方法...
#include <chrono>
#include <condition_variable>
#include <mutex>

class CountDownLatch {
public:
    explicit CountDownLatch(const unsigned int count): m_count(count) { }
    virtual ~CountDownLatch() = default;

    void await(void) {
        std::unique_lock<std::mutex> lock(m_mutex);
        if (m_count > 0) {
            m_cv.wait(lock, [this](){ return m_count == 0; });
        }
    }

    template <class Rep, class Period>
    bool await(const std::chrono::duration<Rep, Period>& timeout) {
        std::unique_lock<std::mutex> lock(m_mutex);
        bool result = true;
        if (m_count > 0) {
            result = m_cv.wait_for(lock, timeout, [this](){ return m_count == 0; });
        }

        return result;
    }

    void countDown(void) {
        std::unique_lock<std::mutex> lock(m_mutex);
        if (m_count > 0) {
            m_count--;
            m_cv.notify_all();
        }
    }

    unsigned int getCount(void) {
        std::unique_lock<std::mutex> lock(m_mutex);
        return m_count;
    }

protected:
    std::mutex m_mutex;
    std::condition_variable m_cv;
    unsigned int m_count = 0;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接