C++ (Qt)#ifndef ATOMICDATA_H#define ATOMICDATA_H #include <asm/atomic.h> template <class T>class AtomicData{private: AtomicData() { m_key1 = ATOMIC_INIT(-1); m_key2 = ATOMIC_INIT(-1); } void setData(const T &data) { while (!test_for_write(&m_key1, &m_key2)); // critical section m_data = data; atomic_set(&m_key1, -1); atomic_set(&m_key2, -1); } T getData() const { while (!test_for_read(&m_key1)); // critical section T res = m_data; atomic_set(&m_key1, -1); atomic_set(&m_key2, -1); return res; }private: atomic_t m_key1; atomic_t m_key2; T m_data; static bool test_for_write(atomic_t *key1, atomic_t *key2) { bool res1 = atomic_inc_and_test(key1); bool res2 = atomic_inc_and_test(key2); atomic_set(key1, 0); atomic_set(key2, 0); return (res1 && res2); } static bool test_for_read(atomic_t *key1) { bool res = atomic_inc_and_test(key1); atomic_set(&m_key2, 0); atomic_set(key1, -1); return res; }}; #endif // ATOMICDATA_H
C++ (Qt)#ifndef ATOMICDATA_H#define ATOMICDATA_H #include <cstdatomic> template <class T>class AtomicData{private: typedef atomic<int> AtomicInt; AtomicData() : m_key1(-1), m_key2(-1) {} void setData(const T &data) { while (!test_for_write(m_key1, m_key2)); // critical section m_data = data; m_key1 = -1; m_key2 = -1; } T getData() const { while (!test_for_read(m_key1, m_key2)); // critical section T res = m_data; m_key1 = -1; m_key2 = -1; return res; }private: AtomicInt m_key1; AtomicInt m_key2; T m_data; static bool test_for_write(AtomicInt &key1, AtomicInt &key2) { bool res1 = (++key1 == 0); bool res2 = (++key2 == 0); key1 = 0; key2 = 0; return (res1 && res2); } static bool test_for_read(AtomicInt &key1, AtomicInt &key2) { bool res = (++key1 == 0); key2 = 0; key1 = -1; return res; }};
C++ (Qt) static bool test_for_read(AtomicInt &key1, AtomicInt &key2) { bool res = (++key1 == 0); key2 = 0; key1 = -1; return res; }};
C++ (Qt)res1 = (++key == 0)
C++ (Qt) T getData() const { while (!test_for_read(m_key1, m_key2)); // critical section T res = m_data; m_key1 = -1; m_key2 = -1; return res; }
C++ (Qt) static bool test_for_write(AtomicInt &key1, AtomicInt &key2) { bool res1 = (++key1 == 0); bool res2 = (++key2 == 0); key1 = 0; key2 = 0; return (res1 && res2); }
C++ (Qt)bool AcquireWrite( AtomicInt & state ){ if (state > 0) return false; return CompareAndSwap(&state, 0, STATE_WRITE);} void ReleaseWrite( AtomicInt & state ){ state = 0;} bool AcquireRead( AtomicInt & state ){ int temp = state; if (temp == STATE_WRITE) return false; return CompareAndSwap(&state, temp, temp + 1);} void ReleaseRead( AtomicInt & state ){ assert(state > 0); --state;}
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; while (result != m_data2) result = m_data1; return result; } // called by writer thread (single thread) void setData(const Data& value) { if (value == m_data1) return; m_data1.directAssignment(value); m_data2.reverseAssignment(value); }private: volatile Data m_data1; volatile Data m_data2;}
C++ (Qt) const Data data() const { const Data result = m_data1; /*B*/ while (result != m_data2) result = m_data1; return result; } void setData (const Data & value) { if (value == m_data1) return; m_data1.directAssignment(value); /*A*/ m_data2.reverseAssignment(value); }