template <class T>class SpinLock{public: const T getData() const { m_state.fetchAndInc(); // add reader while (m_state & WriterMask); // writer presence const T result = m_data; m_state.fetchAndDec(); // remove reader return result; } void setData(const T &data) { while (m_state.fetchAndOr(WriterMask) & ReadersMask); // readers presence m_state.fetchAndXor(WriterMask); // remove writer presence to prevent deadlock m_data = data; m_state.fetchAndXor(WriterMask); // remove writer presence }private: static const int WriterMask = 0x80000000; static const int ReaderMask = 0xFFFFFFFF ^ WriterMask; AtomicInt m_state; T m_data;};
... while (m_state.fetchAndOr(WriterMask) & ReadersMask) { // readers presence m_state.fetchAndXor(WriterMask); // remove writer presence to prevent deadlock sleep(0); }...
C++ (Qt)#define FLAG_WRITE 1 // флаг запись #define FLAG_PENDING 2 // запрос запись #define FLAG_WRITE_PENDING (FLAG_WRITE | FLAG_PENDING) #define NUM_READERS(a) ((a) >> 2) bool AcquireWrite( AtomicInt & state ){ int curValue = state; if (curValue & FLAG_WRITE) // кто-то уже пишет? return false; if (!NUM_READERS(curValue)) // нет читающих, пытаемся захватить по записи return CompareAndSwap(&state, curValue, FLAG_WRITE_PENDING); if ((curValue & FLAG_PENDING) == 0) // пытаемся долить запрос на запись CompareAndSwap(&state, curValue, curValue | FLAG_PENDING); return false;} bool AcquireRead( AtomicInt & state ){ int curValue = state; if (curValue & FLAG_WRITE_PENDING) // кто-то пишет или хочет писать return false; return CompareAndSwap(&state, curValue, (NUM_READERS(curValue) + 1) << 2);} void Release( AtomicInt & state ){ int curValue = state; if (curValue & FLAG_WRITE) { // сброс записи assert(NUM_READERS(curValue) == 0); state = 0; } else { // уменьшаем число читающих, но не должны потерять FLAG_PENDING, поэтому while assert(NUM_READERS(curValue) > 0); while (true) { curValue = state; int newValue = (curValue & FLAG_WRITE_PENDING) | ((NUM_READERS(curValue) - 1) << 2); if (CompareAndSwap(&state, curValue, newValue)) return; } }}
C++ (Qt) static bool acquireRead(AtomicInt &counter, AtomicInt &state) { int tmp = (state |= STATE_READ); if (tmp == STATE_READ) {
C++ (Qt)struct mutex{ atomic_int n = 0; int level = 1; lock () { int nn = ++n; //atomic pre increment while (nn != level); } unlock () { ++level; //non-atomic, but protected by our newborn mutex! }};
C++ (Qt)struct mutex{ atomic_int n = 0; int level = 1; lock () { int nn = ++n; //atomic pre increment while (nn != level); } unlock () { level = nn + 1; //non-atomic, but protected by our newborn mutex! }};
C++ (Qt)struct semaphore{ volatile int n; semaphore( int _n ) : n(_n) {} void acquire( void ) { while (true) { // нагреваем процессор... int value = n; if (value && CompareAndSwap(&n, value, value - 1)) break; } } void release( void ) { ++n; }};
C++ (Qt)void unlock (){ level++;}
C++ (Qt)class mutex{ atomic_int key = -1; public: lock () { int tmp = 0; do { tmp = ++key; if (tmp) key--; } while (tmp != 0); } unlock () { key = -1; }};
C++ (Qt)struct rw_lock{ bool m_writer = false; int m_readers = 0; mutex m_mutex; lock_read () { while (true) { scoped_lock sl (m_mutex); if (!m_writer) { ++m_readers; return; } } } unlock_read () { scoped_lock sl (m_mutex); --m_readers; } lock_write () { while (true) { scoped_lock sl (m_mutex); if (!m_readers && !m_writer) { m_writer = true; return; } } } unlock_write () { scoped_lock sl (m_mutex); m_write = false; }};