Add impl of TSLQueue (TODO UnitTests)

This commit is contained in:
Stephen Seo 2019-10-24 17:49:28 +09:00
parent 0402442929
commit 04d8abab84

View file

@ -3,6 +3,8 @@
#include <memory>
#include <mutex>
#include <thread>
#include <chrono>
#include <optional>
#include <list>
@ -24,7 +26,9 @@ class TSLQueue {
TSLQueue &operator=(TSLQueue &&other);
bool push(const T &data);
bool push_nb(const T &data);
std::optional<T> top();
std::optional<T> top_nb();
bool pop();
std::optional<T> top_and_pop();
std::optional<T> top_and_pop_and_empty(bool *isEmpty);
@ -35,7 +39,11 @@ class TSLQueue {
template <bool isConst, bool isRev>
class TSLQIterWrapper {
public:
TSLQIterWrapper(std::conditional_t<isConst, const std::list<T>, std::list<T>> *container, std::weak_ptr<void> iterValid);
TSLQIterWrapper(
std::conditional_t<isConst, const std::list<T>, std::list<T>> *container,
std::weak_ptr<void> iterValid,
std::shared_ptr<void> iterWrapperCount
);
bool isValid() const;
@ -56,16 +64,28 @@ class TSLQueue {
iter;
std::weak_ptr<void> iterValid;
std::shared_ptr<void> iterWrapperCount;
};
TSLQIterWrapper<false, false> iter();
TSLQIterWrapper<false, true> riter();
TSLQIterWrapper<true, false> citer();
TSLQIterWrapper<true, true> criter();
private:
std::shared_ptr<void> iterValid;
std::shared_ptr<void> iterWrapperCount;
std::mutex mutex;
std::list<T> container;
};
// implementation
template <typename T>
TSLQueue<T>::TSLQueue() {
TSLQueue<T>::TSLQueue() :
iterValid(std::make_shared<void>()),
iterWrapperCount(std::make_shared<void>())
{
}
template <typename T>
@ -73,20 +93,144 @@ TSLQueue<T>::~TSLQueue() {
}
template <typename T>
TSLQueue<T>::TSLQueue(TSLQueue &&other) {
TSLQueue<T>::TSLQueue(TSLQueue &&other) :
iterValid(std::make_shared<void>()),
iterWrapperCount(std::make_shared<void>())
{
std::lock_guard lock(other.mutex);
container = std::move(other.container);
}
template <typename T>
TSLQueue<T> & TSLQueue<T>::operator=(TSLQueue &&other) {
std::scoped_lock lock(mutex, other.mutex);
container = std::move(other.container);
}
template <typename T>
bool TSLQueue<T>::push(const T &data) {
while(iterWrapperCount.use_count() > 1) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::lock_guard lock(mutex);
container.push_back(data);
return true;
}
template <typename T>
bool TSLQueue<T>::push_nb(const T &data) {
if(iterWrapperCount.use_count() > 1) {
return false;
} else if(mutex.try_lock()) {
container.push_back(data);
mutex.unlock();
return true;
} else {
return false;
}
}
template <typename T>
std::optional<T> TSLQueue<T>::top() {
while(iterWrapperCount.use_count() > 1) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::lock_guard lock(mutex);
if(container.empty()) {
return std::nullopt;
} else {
return container.front();
}
}
template <typename T>
std::optional<T> TSLQueue<T>::top_nb() {
if(iterWrapperCount.use_count() > 1) {
return std::nullopt;
} else if(mutex.try_lock()) {
std::optional<T> ret = container.front();
mutex.unlock();
return ret;
} else {
return std::nullopt;
}
}
template <typename T>
bool TSLQueue<T>::pop() {
while(iterWrapperCount.use_count() > 1) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::lock_guard lock(mutex);
if(container.empty()) {
return false;
} else {
container.pop_front();
iterValid = std::make_shared<void>();
iterWrapperCount = std::make_shared<void>();
return true;
}
}
template <typename T>
std::optional<T> TSLQueue<T>::top_and_pop() {
std::optional<T> ret = std::nullopt;
while(iterWrapperCount.use_count() > 1) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::lock_guard lock(mutex);
if(!container.empty()) {
ret = container.front();
container.pop_front();
iterValid = std::make_shared<void>();
iterWrapperCount = std::make_shared<void>();
}
return ret;
}
template <typename T>
std::optional<T> TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) {
std::optional<T> ret = std::nullopt;
while(iterWrapperCount.use_count() > 1) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::lock_guard lock(mutex);
if(container.empty()) {
if(isEmpty) {
*isEmpty = true;
}
} else {
ret = container.front();
container.pop_front();
iterValid = std::make_shared<void>();
iterWrapperCount = std::make_shared<void>();
if(isEmpty) {
*isEmpty = container.empty();
}
}
return ret;
}
template <typename T>
void TSLQueue<T>::clear() {
while(iterWrapperCount.use_count() > 1) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::lock_guard lock(mutex);
container.clear();
iterValid = std::make_shared<void>();
iterWrapperCount = std::make_shared<void>();
}
template <typename T>
template <bool isConst, bool isRev>
TSLQueue<T>::TSLQIterWrapper<isConst, isRev>::TSLQIterWrapper(
std::conditional_t<isConst, const std::list<T>, std::list<T>> *container,
std::weak_ptr<void> iterValid) :
std::weak_ptr<void> iterValid,
std::shared_ptr<void> iterWrapperCount) :
containerPtr(container),
iterValid(iterValid) {
iterValid(iterValid),
iterWrapperCount(iterWrapperCount) {
if constexpr (isRev) {
if constexpr (isConst) {
iter = containerPtr->crbegin();
@ -180,4 +324,24 @@ std::optional<T> TSLQueue<T>::TSLQIterWrapper<isConst, isRev>::current() {
return *iter;
}
template <typename T>
typename TSLQueue<T>::template TSLQIterWrapper<false, false> TSLQueue<T>::iter() {
return TSLQIterWrapper<false, false>(&container, iterValid, iterWrapperCount);
}
template <typename T>
typename TSLQueue<T>::template TSLQIterWrapper<false, true> TSLQueue<T>::riter() {
return TSLQIterWrapper<false, true>(&container, iterValid, iterWrapperCount);
}
template <typename T>
typename TSLQueue<T>::template TSLQIterWrapper<true, false> TSLQueue<T>::citer() {
return TSLQIterWrapper<true, false>(&container, iterValid, iterWrapperCount);
}
template <typename T>
typename TSLQueue<T>::template TSLQIterWrapper<true, true> TSLQueue<T>::criter() {
return TSLQIterWrapper<true, true>(&container, iterValid, iterWrapperCount);
}
#endif