mercredi 5 février 2020

using atomic c++11 to implement a thread safe down counter to zero

I'm new to atomic techniques and try to implement a safe thread version for the follow code:

// say m_cnt is unsigned

void Counter::dec_counter()
{
    if(0==m_cnt)
       return;

    --m_cnt;
    if(0 == m_cnt)
    {
        // Do seomthing
    }
}

Every thread that calls dec_counter must decrement it by one and "Do something" should be done only one time - at when the counter is decremented to 0. After fighting with it, I did the follow code that does it well (I think), but I wonder if this is the way to do it, or is there a better way. Thanks.

// m_cnt is std::atomic<unsigned> 

void Counter::dec_counter()
{
        // loop until decrement done
        unsigned uiExpectedValue;
        unsigned uiNewValue;
        do
        {
            uiExpectedValue = m_cnt.load();

            // if other thread already decremented it to 0, then do nothing.
            if (0 == uiExpectedValue)
                return;

            uiNewValue = uiExpectedValue - 1;

            // at the short time from doing 
            //     uiExpectedValue = m_cnt.load(); 
            // it is possible that another thread had decremented m_cnt, and it won't be equal here to uiExpectedValue,
            // thus the loop, to be sure we do a decrement
        } while (!m_cnt.compare_exchange_weak(uiExpectedValue, uiNewValue));

        // if we are here, that means we did decrement . so if it was to 0, then do something
        if (0 == uiNewValue)
        {
            // do something 
        }

}

Aucun commentaire:

Enregistrer un commentaire