In the case of a shared counter that is waitable (with condition_variable) I wonder what is best regarding the count getter between using an atomic type for the count (mt_counter_B impl) or locking (mt_counter_A impl) ? Also, are the memory_orders that I used correct ? I intend to use the count_relaxed() for a stateless UI so I don't need it to be order-safe.
class mt_counter_A
{
protected:
std::condition_variable cv;
std::mutex cv_m;
uint64_t cnt;
public:
mt_counter_A& operator++() {
{
std::lock_guard<std::mutex> lk(cv_m);
++cnt;
}
cv.notify_all();
}
uint64_t count() {
std::lock_guard<std::mutex> lk(cv_m);
return cnt;
}
void wait_until(uint64_t count) {
std::unique_lock<std::mutex> lk(cv_m);
cv.wait(lk, [&] { return cnt >= count; });
}
};
class mt_counter_B
{
protected:
std::condition_variable cv;
std::mutex cv_m;
std::atomic_uint_fast64_t cnt;
public:
mt_counter_B& operator++() {
{
std::lock_guard<std::mutex> lk(cv_m);
cnt.fetch_add(std::memory_order_relaxed);
}
cv.notify_all();
}
uint64_t count(std::memory_order order = std::memory_order_seq_cst) {
return cnt.load(order);
}
uint64_t count_relaxed() {
return cnt.load(std::memory_order_relaxed);
}
void wait_until(uint64_t count) {
std::unique_lock<std::mutex> lk(cv_m);
cv.wait(lk, [&]{ return cnt.load(std::memory_order_relaxed) >= count; });
}
};
Aucun commentaire:
Enregistrer un commentaire