2023-07-22 09:58:36 +00:00
|
|
|
#include "CXX11_shared_spin_lock.hpp"
|
|
|
|
|
|
|
|
UDPC::Badge UDPC::Badge::newInvalid() {
|
|
|
|
Badge badge;
|
|
|
|
badge.isValid = false;
|
|
|
|
return badge;
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::Badge::Badge() :
|
|
|
|
isValid(true)
|
|
|
|
{}
|
|
|
|
|
|
|
|
UDPC::SharedSpinLock::Ptr UDPC::SharedSpinLock::newInstance() {
|
|
|
|
Ptr sharedSpinLock = Ptr(new SharedSpinLock());
|
|
|
|
sharedSpinLock->selfWeakPtr = sharedSpinLock;
|
|
|
|
return sharedSpinLock;
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::SharedSpinLock::SharedSpinLock() :
|
|
|
|
selfWeakPtr(),
|
2023-10-18 13:28:40 +00:00
|
|
|
spinLock(false),
|
2023-07-22 09:58:36 +00:00
|
|
|
read(0),
|
|
|
|
write(false)
|
|
|
|
{}
|
|
|
|
|
|
|
|
UDPC::LockObj<false> UDPC::SharedSpinLock::spin_read_lock() {
|
2023-10-18 13:28:40 +00:00
|
|
|
bool expected;
|
2023-07-22 09:58:36 +00:00
|
|
|
while (true) {
|
2023-10-18 13:28:40 +00:00
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if(spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-18 13:28:40 +00:00
|
|
|
if (!write) {
|
|
|
|
++read;
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
return LockObj<false>(selfWeakPtr, Badge{});
|
|
|
|
} else {
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::LockObj<false> UDPC::SharedSpinLock::try_spin_read_lock() {
|
2023-10-19 12:07:08 +00:00
|
|
|
bool expected;
|
|
|
|
while (true) {
|
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-19 12:07:08 +00:00
|
|
|
if (!write) {
|
|
|
|
++read;
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
return LockObj<false>(selfWeakPtr, Badge{});
|
|
|
|
} else {
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
break;
|
|
|
|
}
|
2023-10-18 13:28:40 +00:00
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
2023-07-22 10:07:32 +00:00
|
|
|
return LockObj<false>{};
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void UDPC::SharedSpinLock::read_unlock(UDPC::Badge &&badge) {
|
|
|
|
if (badge.isValid) {
|
2023-10-18 13:28:40 +00:00
|
|
|
bool expected;
|
|
|
|
while (true) {
|
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-18 13:28:40 +00:00
|
|
|
if (read > 0) {
|
|
|
|
--read;
|
|
|
|
badge.isValid = false;
|
|
|
|
}
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
break;
|
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::LockObj<true> UDPC::SharedSpinLock::spin_write_lock() {
|
2023-10-18 13:28:40 +00:00
|
|
|
bool expected;
|
2023-07-22 09:58:36 +00:00
|
|
|
while (true) {
|
2023-10-18 13:28:40 +00:00
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-18 13:28:40 +00:00
|
|
|
if (!write && read == 0) {
|
|
|
|
write = true;
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
return LockObj<true>(selfWeakPtr, Badge{});
|
|
|
|
} else {
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::LockObj<true> UDPC::SharedSpinLock::try_spin_write_lock() {
|
2023-10-19 12:07:08 +00:00
|
|
|
bool expected;
|
|
|
|
while (true) {
|
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-19 12:07:08 +00:00
|
|
|
if (!write && read == 0) {
|
|
|
|
write = true;
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
return LockObj<true>(selfWeakPtr, Badge{});
|
|
|
|
} else {
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
break;
|
|
|
|
}
|
2023-10-18 13:28:40 +00:00
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
2023-07-22 10:07:32 +00:00
|
|
|
return LockObj<true>{};
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void UDPC::SharedSpinLock::write_unlock(UDPC::Badge &&badge) {
|
|
|
|
if (badge.isValid) {
|
2023-10-18 13:28:40 +00:00
|
|
|
bool expected;
|
|
|
|
while(true) {
|
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-18 13:28:40 +00:00
|
|
|
if (write) {
|
|
|
|
write = false;
|
|
|
|
badge.isValid = false;
|
|
|
|
}
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::LockObj<false> UDPC::SharedSpinLock::trade_write_for_read_lock(UDPC::LockObj<true> &lockObj) {
|
|
|
|
if (lockObj.isValid() && lockObj.badge.isValid) {
|
2023-10-18 13:28:40 +00:00
|
|
|
bool expected;
|
2023-07-22 09:58:36 +00:00
|
|
|
while (true) {
|
2023-10-18 13:28:40 +00:00
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-18 13:28:40 +00:00
|
|
|
if (write && read == 0) {
|
|
|
|
read = 1;
|
|
|
|
write = false;
|
|
|
|
lockObj.isLocked = false;
|
|
|
|
lockObj.badge.isValid = false;
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
return LockObj<false>(selfWeakPtr, Badge{});
|
|
|
|
} else {
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2023-07-22 10:07:32 +00:00
|
|
|
return LockObj<false>{};
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::LockObj<false> UDPC::SharedSpinLock::try_trade_write_for_read_lock(UDPC::LockObj<true> &lockObj) {
|
|
|
|
if (lockObj.isValid() && lockObj.badge.isValid) {
|
2023-10-19 12:07:08 +00:00
|
|
|
bool expected;
|
|
|
|
while (true) {
|
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-19 12:07:08 +00:00
|
|
|
if (write && read == 0) {
|
|
|
|
read = 1;
|
|
|
|
write = false;
|
|
|
|
lockObj.isLocked = false;
|
|
|
|
lockObj.badge.isValid = false;
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
return LockObj<false>(selfWeakPtr, Badge{});
|
|
|
|
} else {
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
break;
|
|
|
|
}
|
2023-10-18 13:28:40 +00:00
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
2023-07-22 10:07:32 +00:00
|
|
|
return LockObj<false>{};
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::LockObj<true> UDPC::SharedSpinLock::trade_read_for_write_lock(UDPC::LockObj<false> &lockObj) {
|
|
|
|
if (lockObj.isValid() && lockObj.badge.isValid) {
|
2023-10-18 13:28:40 +00:00
|
|
|
bool expected;
|
2023-07-22 09:58:36 +00:00
|
|
|
while (true) {
|
2023-10-18 13:28:40 +00:00
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-18 13:28:40 +00:00
|
|
|
if (!write && read == 1) {
|
|
|
|
read = 0;
|
|
|
|
write = true;
|
|
|
|
lockObj.isLocked = false;
|
|
|
|
lockObj.badge.isValid = false;
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
return LockObj<true>(selfWeakPtr, Badge{});
|
|
|
|
} else {
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2023-07-22 10:07:32 +00:00
|
|
|
return LockObj<true>{};
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC::LockObj<true> UDPC::SharedSpinLock::try_trade_read_for_write_lock(UDPC::LockObj<false> &lockObj) {
|
|
|
|
if (lockObj.isValid() && lockObj.badge.isValid) {
|
2023-10-19 12:07:08 +00:00
|
|
|
bool expected;
|
|
|
|
while (true) {
|
|
|
|
expected = false;
|
2023-12-19 04:47:19 +00:00
|
|
|
if (spinLock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {
|
2023-10-19 12:07:08 +00:00
|
|
|
if (!write && read == 1) {
|
|
|
|
read = 0;
|
|
|
|
write = true;
|
|
|
|
lockObj.isLocked = false;
|
|
|
|
lockObj.badge.isValid = false;
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
return LockObj<true>(selfWeakPtr, Badge{});
|
|
|
|
} else {
|
|
|
|
spinLock.store(false, std::memory_order_release);
|
|
|
|
break;
|
|
|
|
}
|
2023-10-18 13:28:40 +00:00
|
|
|
}
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
2023-07-22 10:07:32 +00:00
|
|
|
return LockObj<true>{};
|
2023-07-22 09:58:36 +00:00
|
|
|
}
|