0

I have one atomic integer variable which has a minimum and maximum value. Two threads update the variable, one increments it and the other decrements it. If incrementing would increase the value over the maximum value, the thread blocks and waits for a condition variable. Same thing happens with decrementing when the value hits the minimum. When the value is decremented and the old value is the maximum value, decrementing thread should notify incrementing thread and same thing should happen the other way around when incrementing.

Decrementing function body:

if (atomic_var.load(std::memory_order_acquire) == minimum) {
    std::unique_lock<std::mutex> lk(mutex);
    if (atomic_var.load(std::memory_order_acquire) == minimum) {
        //we have hit the minimum so we have to wait for the other thread to increase the variable
        condition_var.wait(lk, [&]() {
            return atomic_var.load(std::memory_order_relaxed) > minimum;
        });
    }

    //do stuff

    std::atomic_fetch_sub_explicit(&atomic_var, 1u, std::memory_order_release);
    lk.unlock();
    condition_var.notify_all();
    return;
}

//do stuff

if (std::atomic_fetch_sub_explicit(&atomic_var, 1u, std::memory_order_release) == maximum) {
    //we have hit the maximum so the other thread might be waiting
    std::atomic_thread_fence(std::memory_order_acquire);
    condition_var.notify_all();
}
//adding condition_var.notify_all() here fixes the problem but I'm afraid
//that causes a bit too great performance penalty when it could be easily avoided

Which memory orderings I should use for these checks? My current implementation seems to cause dead locks...

Edit: Changing all memory orders to std::memory_order_seq_cst doesn't seem to remove the problem.

4
  • 1) If you use memory_order_seq_cst for all of them, do the deadlocks disappear? 2) If that resolves the deadlocks, do you have measurements showing that using memory_order_seq_cst is actually causing a significant performance degradation? Commented Apr 28, 2015 at 5:38
  • @T.C. Using std::memory_order_seq_cst doesn't seem to fix the problem. Commented Apr 28, 2015 at 10:15
  • Then it's a problem in your design, not in the memory order. Commented Apr 28, 2015 at 15:20
  • Do you have a very good reason to use anything other than std::memory_order_seq_cst and can you prove its correctness? Otherwise, according to answers in this question, you should not. Having said that, if you still have a deadlock when using std::memory_order_seq_cst, then there's a race condition (or other design flaw) somewhere, which we cannot identify for you with only (part of) the source code of the decrementing function body. Commented Apr 30, 2015 at 7:58

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.