C++ (Qt) const Data data() const { const Data result = m_data1; /*B*/ while (result != m_data1 || result != m_data2) result = m_data1; return result; }
C++ (Qt)#ifndef ATOMICDATA_H#define ATOMICDATA_H #include <assert.h>#include <cstdatomic> template <class T>class AtomicData{public: typedef atomic<int> AtomicInt; AtomicData() : m_count_readers(0), m_state_write(-1) {} void setData(const T &data) { while (!acquireWrite(m_count_readers, m_state_write)); m_data = data; releaseWrite(m_state_write); } T getData() const { while (!acquireRead(m_count_readers, m_state_write)); T data = m_data; releaseRead(m_count_readers, m_state_write); return data; }private: AtomicInt m_count_readers; AtomicInt m_state_write; T m_data; static bool acquireWrite(AtomicInt &readers, AtomicInt &state_write) { bool tmp = (++state_write == 0); state_write = 0; return (tmp && !readers); } //------------------------------------------------------------------------- static void releaseWrite(AtomicInt &state_write) { state_write = -1; } //------------------------------------------------------------------------- static bool acquireRead(AtomicInt &readers, AtomicInt &state_write) { if (!readers) readers = (state_write == -1); else readers++; return readers; } //------------------------------------------------------------------------- static void releaseRead(AtomicInt &readers, AtomicInt &state_write) { if (--readers == 0) state_write = -1; } //-------------------------------------------------------------------------}; #endif // ATOMICDATA_H
C++ (Qt) if (!readers) readers = (state_write == -1);
C++ (Qt)static bool acquireRead(AtomicInt &readers, AtomicInt &state_write) { if (!readers) readers = 1; // атомарно int tmp = (state_write == -1); // атомарно readers = tmp; // атомарно else readers++; return readers; }
C++ (Qt) if (!readers) readers = 1; // атомарно
C++ (Qt)static bool acquireRead(AtomicInt &readers, AtomicInt &state_write) { if (!readers) { int tmp = (++state_write == 0); readers = tmp; } else readers++; return readers; }
C++ (Qt)#ifndef SPINLOCK_H#define SPINLOCK_H #include <assert.h>#include <cstdatomic> template <class T>class SpinLock{public: typedef atomic<int> AtomicInt; SpinLock() : m_count_readers(0), m_state_write(-1) {} void setData(const T &data) { while (!acquireWrite(m_count_readers, m_state_write)); m_data = data; releaseWrite(m_state_write); } T getData() const { while (!acquireRead(m_count_readers, m_state_write)); T data = m_data; releaseRead(m_count_readers, m_state_write); return data; }private: AtomicInt m_count_readers; AtomicInt m_state_write; T m_data; static bool acquireWrite(AtomicInt &readers, AtomicInt &state_write) { bool tmp = (++state_write == 0); state_write = 0; return (tmp && !readers); } //------------------------------------------------------------------------- static void releaseWrite(AtomicInt &state_write) { state_write = -1; } //------------------------------------------------------------------------- static bool acquireRead(AtomicInt &readers, AtomicInt &state_write) { if (!readers) { int tmp = (++state_write == 0); readers = tmp; } else readers++; return readers; } //------------------------------------------------------------------------- static void releaseRead(AtomicInt &readers, AtomicInt &state_write) { if (--readers == 0) state_write = -1; } //-------------------------------------------------------------------------}; #endif // SPINLOCK_H
C++ (Qt)static bool acquireRead(AtomicInt &readers, AtomicInt &state_write){ if (!readers) { int tmp = (++state_write == 0); readers = tmp; } else readers++; return readers;}
struct Data { int a; int b; ... Data& directAssignment(const Data& other) { a = other.a; b = other.b; ... return *this; } Data& reverseAssignment(const Data& other) { b = other.b; a = other.a; ... return *this; }};class DataManager{public: // called by reader threads (several threads) const Data data() const { const Data result = m_data1; int counter = counter_; while (result != m_data2 || counter != counter_) { result = m_data1; counter = counter_; } return result; } // called by writer thread (single thread) void setData(const Data& value) { if (value == m_data1) return; ++counter_; m_data1.directAssignment(value); m_data2.reverseAssignment(value); }private: volatile Data m_data1; volatile Data m_data2; volatile int counter_;}