这个问题是在这个问题上提出的。
将while-loop转换为使用std::condition_variable的条件等待之后,我想知道这段在C++11中实现std::latch来自C++20的的代码是否还存在任何缺陷/问题:
#include <condition_variable>
#include <cstdint>
#include <atomic>
#include <mutex>
class latch {
std::atomic<std::ptrdiff_t> counter_;
mutable std::condition_variable cv_;
mutable std::mutex mut_;
public:
explicit latch(std::ptrdiff_t const def = 1) : counter_(def) {}
void count_down(std::ptrdiff_t const n = 1) {
counter_ -= n;
cv_.notify_all();
}
void wait() const {
if (counter_.load(std::memory_order_relaxed) == 0) return;
std::unique_lock<std::mutex> lock(mut_);
cv_.wait(lock, [=] { return counter_.load(std::memory_order_relaxed) == 0; });
}
bool try_wait() const noexcept {
return counter_.load(std::memory_order_relaxed) == 0;
}
void arrive_and_wait(std::ptrdiff_t const n = 1) {
count_down(n);
wait();
}
static constexpr std::ptrdiff_t max() noexcept {
return std::numeric_limits<std::ptrdiff_t>::max();
}
};发布于 2021-10-25 10:28:28
对于构造函数,有一些次要的挑剔:
constexpr。max())。标准称它是未定义的行为,因此我们在技术上不必这样做,但对assert来说,这比默默地继续进行要好。另一件事:
counter_ -= n;
cv_.notify_all();operator-=()在做counter.fetch_sub(n, std::memory_order_seq_cst);。
虽然这个内存顺序是安全的,但我不确定它是否必要。我怀疑你可以摆脱std::memory_order_release (注意:我不太熟悉atomic<>s,所以你可能需要一个第二种意见)。
在任何情况下,使用显式fetch_sub调用更清楚,并且还允许我们添加一个断言,即以前的counter值大于或等于n。
https://codereview.stackexchange.com/questions/269344
复制相似问题