Created
January 30, 2019 22:28
-
-
Save gekomad/e6fee9a1d525e33d78855dce6e5e8f78 to your computer and use it in GitHub Desktop.
A C++ shared Spinlock implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <atomic> | |
using namespace std; | |
#ifdef _WIN32 | |
#include <intrin.h> | |
#pragma intrinsic(_InterlockedExchange) | |
#define LOCK_TEST_AND_SET(_lock) _InterlockedExchange(&_lock, 1) | |
#define LOCK_RELEASE(_lock) _InterlockedExchange(&_lock, 0) | |
#else | |
#define LOCK_TEST_AND_SET(_lock) __sync_lock_test_and_set(&_lock, 1) | |
#define LOCK_RELEASE(_lock) __sync_lock_release(&_lock) | |
#endif | |
class Spinlock { | |
private: | |
std::atomic_flag flag; | |
volatile long _write = 0; | |
volatile atomic_int _read; | |
void _lock() { | |
while (true) { | |
if (!LOCK_TEST_AND_SET(_write)) | |
return; | |
while (_write); | |
} | |
} | |
public: | |
Spinlock() : _read(false), flag(ATOMIC_FLAG_INIT) { } | |
inline void lock() { | |
while (flag.test_and_set(std::memory_order_acquire)); | |
} | |
inline void unlock() { | |
flag.clear(std::memory_order_release); | |
} | |
inline void lockWrite() { | |
bool w = false; | |
while (true) { | |
if (!w && !LOCK_TEST_AND_SET(_write)) { | |
w = true; | |
} | |
if (w && !_read) { | |
return; | |
} | |
while ((!w && _write) || _read); | |
} | |
} | |
inline void unlockWrite() { | |
LOCK_RELEASE(_write); | |
} | |
inline void lockRead() { | |
lockWrite(); | |
_read++; | |
unlockWrite(); | |
} | |
inline void unlockRead() { | |
_read--; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment