可以将std :: condition_variables用作计数信号量吗?

时间:2016-10-31 02:03:09

标签: c++ multithreading c++11 semaphore condition-variable

这是Can C++11 condition_variables be used to synchronize processes?的后续行动。

std :: condition_variable对象可以用作计数信号量吗?

Methinks不是因为对象似乎绑定到std :: mutex,这意味着它只能用作二进制信号量。我已经在线查看过,包括hereherehere,但无法找到使用这些对象作为计算信号量的参考或示例。

1 个答案:

答案 0 :(得分:2)

struct counting_sem {
  counting_sem(std::ptrdiff_t init=0):count(init) {}
  // remove in C++17:
  counting_sem(counting_sem&& src) {
    auto l = src.lock(); // maybe drop, as src is supposed to be dead
    count = src.count;
  }
  counting_sem& operator=(counting_sem&& src) = delete;
  void take( std::size_t N=1 ) {
    if (N==0) return;
    auto l = lock();
    cv.wait(l, [&]{
      if (count > 0 && count < (std::ptrdiff_t)N) {
        N -= count;
        count = 0;
      } else if (count >= (std::ptrdiff_t)N) {
        count -= N;
        N = 0;
      }
      return N == 0;
    });
  }
  void give( std::size_t N=1 ) {
    if (N==0) return;
    {
      auto l = lock();
      count += N;
    }
    cv.notify_all();
  }
  // reduce the count without waiting for it
  void reduce(std::size_t N=1) {
    if (N==0) return;
    auto l = lock();
    count -= N;
  }
private:
  std::mutex m;
  std::condition_variable cv;
  std::ptrdiff_t count;

  auto lock() {
    return std::unique_lock<std::mutex>(m);
  }
  auto unlocked() {
    return std::unique_lock<std::mutex>(m, std::defer_lock_t{});
  }
};

代码未经过测试或编译,但设计合理。

take(7)不等同于for(repeat 7 times) take():相反,如果不够,则需要尽可能多的阻止。

修改以便在有足够的东西之前不会采取任何措施:

      if (count >= (std::ptrdiff_t)N) {
        count -= N;
        N = 0;
      }
相关问题