2017-01-30 3 views
2

Ich schreibe Multithreaded Socket-Klasse. Die Funktion BelowBounds() kann von mehreren Threads gleichzeitig aufgerufen werden, ich muss die Verwendung von Mutexes verhindern. Ist dieser Code Thread-sicher?Ist atomare Zunahme und comparison thread-safe

class UDPSocketHT 
{ 
public: 
    std::atomic<size_t> m_nSimultaneousRecvCalls; 
    std::atomic<size_t> m_nPendingOperations; 
    //... 
    bool UDPSocketHT::BelowBounds () 
    { 
     return (!m_nSimultaneousRecvCalls || (m_nPendingOperations + 1 <= m_nSimultaneousRecvCalls)) ? true : false; 
    } 
} 

Oder muss ich auf diese Weise schreiben?

bool UDPSocketHT::BelowBounds () 
{ 
    size_t x = m_nSimultaneousRecvCalls; 
    size_t y = m_nPendingOperations; 
    return (!x || (y + 1 <= x)) ? true : false; 
} 
+1

Nicht verwandt mit Ihrer Frage, aber wenn Sie einen ternären Ausdruck haben, der zu 'true' oder' false' führt, brauchen Sie keinen ternären Ausdruck. In Ihrem letzten Beispiel könnten Sie genauso gut 'return! X || schreiben (y + 1 <= x); ' –

Antwort

5

Ihre beiden Alternativen sind unsicher. Jede atomare Variable von sich aus ist atomar, aber die Verwendung von zwei von ihnen in einer einzigen Anweisung ist nicht.

Sie können Ihren Check in einen Mutex einbinden oder einen Weg finden, ein einzelnes Atom zu verwenden.

Welche Operationen an std::atomic sind atomar?

  • operator= speichert ein neuer Wert atomar

  • load() oder operator T (in einem Ausdruck verwendet wird) liest der Wert atomar

  • operator++ Wert inkrementiert atomar

  • compare_exchange_weak/strong Prüfung und setze den Wert atomar

  • more details

Mit zwei atomics in einem Ausdruck ist nicht atomar: a + b liest a atomar, dannb atomar lesen, aber alles kann passieren in zwischen a und b zu lesen; Wenn Sie b lesen, kann a bereits einen anderen Wert haben.