+++ /dev/null
-#include "CXX11_shared_spin_lock.hpp"
-
-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(),
-mutex(),
-read(0),
-write(false)
-{}
-
-UDPC::LockObj<false> UDPC::SharedSpinLock::spin_read_lock() {
- while (true) {
- std::lock_guard<std::mutex> lock(mutex);
- if (!write.load()) {
- ++read;
- return LockObj<false>(selfWeakPtr, Badge{});
- }
- }
-}
-
-UDPC::LockObj<false> UDPC::SharedSpinLock::try_spin_read_lock() {
- std::lock_guard<std::mutex> lock(mutex);
- if (!write.load()) {
- ++read;
- return LockObj<false>(selfWeakPtr, Badge{});
- }
- return LockObj<false>(Badge{});
-}
-
-void UDPC::SharedSpinLock::read_unlock(UDPC::Badge &&badge) {
- if (badge.isValid) {
- std::lock_guard<std::mutex> lock(mutex);
- if (read.load() > 0) {
- --read;
- badge.isValid = false;
- }
- }
-}
-
-UDPC::LockObj<true> UDPC::SharedSpinLock::spin_write_lock() {
- while (true) {
- std::lock_guard<std::mutex> lock(mutex);
- if (!write.load() && read.load() == 0) {
- write.store(true);
- return LockObj<true>(selfWeakPtr, Badge{});
- }
- }
-}
-
-UDPC::LockObj<true> UDPC::SharedSpinLock::try_spin_write_lock() {
- std::lock_guard<std::mutex> lock(mutex);
- if (!write.load() && read.load() == 0) {
- write.store(true);
- return LockObj<true>(selfWeakPtr, Badge{});
- }
- return LockObj<true>(Badge{});
-}
-
-void UDPC::SharedSpinLock::write_unlock(UDPC::Badge &&badge) {
- if (badge.isValid) {
- std::lock_guard<std::mutex> lock(mutex);
- write.store(false);
- badge.isValid = false;
- }
-}
+++ /dev/null
-#ifndef UDPC_CXX11_SHARED_SPIN_LOCK_H_
-#define UDPC_CXX11_SHARED_SPIN_LOCK_H_
-
-#include <memory>
-#include <mutex>
-#include <atomic>
-
-namespace UDPC {
-
-// Forward declaration for LockObj.
-class SharedSpinLock;
-
-class Badge {
-public:
- // Disallow copy.
- Badge(const Badge&) = delete;
- Badge& operator=(const Badge&) = delete;
-
- // Allow move.
- Badge(Badge&&) = default;
- Badge& operator=(Badge&&) = default;
-
-private:
- friend class SharedSpinLock;
-
- // Can only be created by SharedSpinLock.
- Badge();
-
- bool isValid;
-};
-
-template <bool IsWriteObj>
-class LockObj {
-public:
- ~LockObj();
-
- // Disallow copy.
- LockObj(const LockObj&) = delete;
- LockObj& operator=(const LockObj&) = delete;
-
- // Allow move.
- LockObj(LockObj&&) = default;
- LockObj& operator=(LockObj&&) = default;
-
- bool isValid() const;
-
-private:
- friend class SharedSpinLock;
-
- // Only can be created by SharedSpinLock.
- LockObj(Badge &&badge);
- LockObj(std::weak_ptr<SharedSpinLock> lockPtr, Badge &&badge);
-
- std::weak_ptr<SharedSpinLock> weakPtrLock;
- bool isLocked;
- Badge badge;
-};
-
-class SharedSpinLock {
-public:
- using Ptr = std::shared_ptr<SharedSpinLock>;
- using Weak = std::weak_ptr<SharedSpinLock>;
-
- static Ptr newInstance();
-
- // Disallow copy.
- SharedSpinLock(const SharedSpinLock&) = delete;
- SharedSpinLock& operator=(const SharedSpinLock&) = delete;
-
- // Allow move.
- SharedSpinLock(SharedSpinLock&&) = default;
- SharedSpinLock& operator=(SharedSpinLock&&) = default;
-
- LockObj<false> spin_read_lock();
- LockObj<false> try_spin_read_lock();
- void read_unlock(Badge&&);
-
- LockObj<true> spin_write_lock();
- LockObj<true> try_spin_write_lock();
- void write_unlock(Badge&&);
-
-private:
- SharedSpinLock();
-
- Weak selfWeakPtr;
- std::mutex mutex;
- std::atomic_uint read;
- std::atomic_bool write;
-
-};
-
-template <bool IsWriteObj>
-LockObj<IsWriteObj>::LockObj(Badge &&badge) :
-weakPtrLock(),
-isLocked(false),
-badge(std::forward<Badge>(badge))
-{}
-
-template <bool IsWriteObj>
-LockObj<IsWriteObj>::LockObj(SharedSpinLock::Weak lockPtr, Badge &&badge) :
-weakPtrLock(lockPtr),
-isLocked(true),
-badge(std::forward<Badge>(badge))
-{}
-
-template <bool IsWriteObj>
-LockObj<IsWriteObj>::~LockObj() {
- if (!isLocked) {
- return;
- }
- auto strongPtrLock = weakPtrLock.lock();
- if (strongPtrLock) {
- if (IsWriteObj) {
- strongPtrLock->write_unlock(std::move(badge));
- } else {
- strongPtrLock->read_unlock(std::move(badge));
- }
- }
-}
-
-template <bool IsWriteObj>
-bool LockObj<IsWriteObj>::isValid() const {
- return isLocked;
-}
-
-} // namespace UDPC
-
-#endif
#include <list>
#include <type_traits>
-#include "CXX11_shared_spin_lock.hpp"
-
template <typename T>
class TSLQueue {
public:
class TSLQIter {
public:
- TSLQIter(UDPC::SharedSpinLock::Weak sharedSpinLockWeak,
+ TSLQIter(std::mutex *mutex,
std::weak_ptr<TSLQNode> currentNode,
unsigned long *msize);
~TSLQIter();
bool remove();
private:
- UDPC::SharedSpinLock::Weak sharedSpinLockWeak;
- UDPC::LockObj<false> readLock;
+ std::mutex *mutex;
std::weak_ptr<TSLQNode> currentNode;
unsigned long *const msize;
TSLQIter begin();
private:
- UDPC::SharedSpinLock::Ptr sharedSpinLock;
+ std::mutex mutex;
std::shared_ptr<TSLQNode> head;
std::shared_ptr<TSLQNode> tail;
unsigned long msize;
template <typename T>
TSLQueue<T>::TSLQueue() :
- sharedSpinLock(UDPC::SharedSpinLock::newInstance()),
+ mutex(),
head(std::shared_ptr<TSLQNode>(new TSLQNode())),
tail(std::shared_ptr<TSLQNode>(new TSLQNode())),
msize(0)
template <typename T>
TSLQueue<T> & TSLQueue<T>::operator=(TSLQueue &&other) {
- auto selfWriteLock = sharedSpinLock->spin_write_lock();
- auto otherWriteLock = other.sharedSpinLock->spin_write_lock();
+ std::lock_guard<std::mutex> lock(mutex);
+ std::lock_guard<std::mutex> otherLock(other.mutex);
head = std::move(other.head);
tail = std::move(other.tail);
msize = std::move(other.msize);
template <typename T>
void TSLQueue<T>::push(const T &data) {
- auto writeLock = sharedSpinLock->spin_write_lock();
+ std::lock_guard<std::mutex> lock(mutex);
auto newNode = std::shared_ptr<TSLQNode>(new TSLQNode());
newNode->data = std::unique_ptr<T>(new T(data));
template <typename T>
bool TSLQueue<T>::push_nb(const T &data) {
- auto writeLock = sharedSpinLock->try_spin_write_lock();
- if(writeLock.isValid()) {
+ if(mutex.try_lock()) {
auto newNode = std::shared_ptr<TSLQNode>(new TSLQNode());
newNode->data = std::unique_ptr<T>(new T(data));
tail->prev = newNode;
++msize;
+ mutex.unlock();
return true;
} else {
return false;
template <typename T>
std::unique_ptr<T> TSLQueue<T>::top() {
- auto readLock = sharedSpinLock->spin_read_lock();
+ std::lock_guard<std::mutex> lock(mutex);
std::unique_ptr<T> result;
if(head->next != tail) {
assert(head->next->data);
template <typename T>
std::unique_ptr<T> TSLQueue<T>::top_nb() {
std::unique_ptr<T> result;
- auto readLock = sharedSpinLock->try_spin_read_lock();
- if(readLock.isValid()) {
+ if(mutex.try_lock()) {
if(head->next != tail) {
assert(head->next->data);
result = std::unique_ptr<T>(new T);
*result = *head->next->data;
}
+ mutex.unlock();
}
return result;
}
template <typename T>
bool TSLQueue<T>::pop() {
- auto writeLock = sharedSpinLock->spin_write_lock();
+ std::lock_guard<std::mutex> lock(mutex);
if(head->next == tail) {
return false;
} else {
template <typename T>
std::unique_ptr<T> TSLQueue<T>::top_and_pop() {
std::unique_ptr<T> result;
- auto writeLock = sharedSpinLock->spin_write_lock();
+ std::lock_guard<std::mutex> lock(mutex);
if(head->next != tail) {
assert(head->next->data);
result = std::unique_ptr<T>(new T);
template <typename T>
std::unique_ptr<T> TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) {
std::unique_ptr<T> result;
- auto writeLock = sharedSpinLock->spin_write_lock();
+ std::lock_guard<std::mutex> lock(mutex);
if(head->next == tail) {
if(isEmpty) {
*isEmpty = true;
template <typename T>
std::unique_ptr<T> TSLQueue<T>::top_and_pop_and_rsize(unsigned long *rsize) {
std::unique_ptr<T> result;
- auto writeLock = sharedSpinLock->spin_write_lock();
+ std::lock_guard<std::mutex> lock(mutex);
if(head->next == tail) {
if(rsize) {
*rsize = 0;
template <typename T>
void TSLQueue<T>::clear() {
- auto writeLock = sharedSpinLock->spin_write_lock();
+ std::lock_guard<std::mutex> lock(mutex);
head->next = tail;
tail->prev = head;
template <typename T>
bool TSLQueue<T>::empty() {
- auto readLock = sharedSpinLock->spin_read_lock();
+ std::lock_guard<std::mutex> lock(mutex);
return head->next == tail;
}
template <typename T>
unsigned long TSLQueue<T>::size() {
- auto readLock = sharedSpinLock->spin_read_lock();
+ std::lock_guard<std::mutex> lock(mutex);
return msize;
}
}
template <typename T>
-TSLQueue<T>::TSLQIter::TSLQIter(UDPC::SharedSpinLock::Weak lockWeak,
+TSLQueue<T>::TSLQIter::TSLQIter(std::mutex *mutex,
std::weak_ptr<TSLQNode> currentNode,
unsigned long *msize) :
-sharedSpinLockWeak(lockWeak),
-readLock(lockWeak.lock()->spin_read_lock()),
+mutex(mutex),
currentNode(currentNode),
msize(msize)
-{}
+{
+ mutex->lock();
+}
template <typename T>
-TSLQueue<T>::TSLQIter::~TSLQIter() {}
+TSLQueue<T>::TSLQIter::~TSLQIter() {
+ mutex->unlock();
+}
template <typename T>
std::unique_ptr<T> TSLQueue<T>::TSLQIter::current() {
template <typename T>
typename TSLQueue<T>::TSLQIter TSLQueue<T>::begin() {
- return TSLQIter(sharedSpinLock, head->next, &msize);
+ return TSLQIter(&mutex, head->next, &msize);
}
#endif