diff --git a/cpp_impl/src/TSLQueue.hpp b/cpp_impl/src/TSLQueue.hpp index 5a0253a..fd42df8 100644 --- a/cpp_impl/src/TSLQueue.hpp +++ b/cpp_impl/src/TSLQueue.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include @@ -24,7 +26,9 @@ class TSLQueue { TSLQueue &operator=(TSLQueue &&other); bool push(const T &data); + bool push_nb(const T &data); std::optional top(); + std::optional top_nb(); bool pop(); std::optional top_and_pop(); std::optional top_and_pop_and_empty(bool *isEmpty); @@ -35,7 +39,11 @@ class TSLQueue { template class TSLQIterWrapper { public: - TSLQIterWrapper(std::conditional_t, std::list> *container, std::weak_ptr iterValid); + TSLQIterWrapper( + std::conditional_t, std::list> *container, + std::weak_ptr iterValid, + std::shared_ptr iterWrapperCount + ); bool isValid() const; @@ -56,16 +64,28 @@ class TSLQueue { iter; std::weak_ptr iterValid; + std::shared_ptr iterWrapperCount; }; + TSLQIterWrapper iter(); + TSLQIterWrapper riter(); + TSLQIterWrapper citer(); + TSLQIterWrapper criter(); + private: std::shared_ptr iterValid; + std::shared_ptr iterWrapperCount; + std::mutex mutex; + std::list container; }; // implementation template -TSLQueue::TSLQueue() { +TSLQueue::TSLQueue() : + iterValid(std::make_shared()), + iterWrapperCount(std::make_shared()) +{ } template @@ -73,20 +93,144 @@ TSLQueue::~TSLQueue() { } template -TSLQueue::TSLQueue(TSLQueue &&other) { +TSLQueue::TSLQueue(TSLQueue &&other) : + iterValid(std::make_shared()), + iterWrapperCount(std::make_shared()) +{ + std::lock_guard lock(other.mutex); + container = std::move(other.container); } template TSLQueue & TSLQueue::operator=(TSLQueue &&other) { + std::scoped_lock lock(mutex, other.mutex); + container = std::move(other.container); +} + +template +bool TSLQueue::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 +bool TSLQueue::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 +std::optional TSLQueue::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 +std::optional TSLQueue::top_nb() { + if(iterWrapperCount.use_count() > 1) { + return std::nullopt; + } else if(mutex.try_lock()) { + std::optional ret = container.front(); + mutex.unlock(); + return ret; + } else { + return std::nullopt; + } +} + +template +bool TSLQueue::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(); + iterWrapperCount = std::make_shared(); + return true; + } +} + +template +std::optional TSLQueue::top_and_pop() { + std::optional 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(); + iterWrapperCount = std::make_shared(); + } + return ret; +} + +template +std::optional TSLQueue::top_and_pop_and_empty(bool *isEmpty) { + std::optional 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(); + iterWrapperCount = std::make_shared(); + if(isEmpty) { + *isEmpty = container.empty(); + } + } + return ret; +} + +template +void TSLQueue::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(); + iterWrapperCount = std::make_shared(); } template template TSLQueue::TSLQIterWrapper::TSLQIterWrapper( std::conditional_t, std::list> *container, - std::weak_ptr iterValid) : + std::weak_ptr iterValid, + std::shared_ptr iterWrapperCount) : containerPtr(container), - iterValid(iterValid) { + iterValid(iterValid), + iterWrapperCount(iterWrapperCount) { if constexpr (isRev) { if constexpr (isConst) { iter = containerPtr->crbegin(); @@ -180,4 +324,24 @@ std::optional TSLQueue::TSLQIterWrapper::current() { return *iter; } +template +typename TSLQueue::template TSLQIterWrapper TSLQueue::iter() { + return TSLQIterWrapper(&container, iterValid, iterWrapperCount); +} + +template +typename TSLQueue::template TSLQIterWrapper TSLQueue::riter() { + return TSLQIterWrapper(&container, iterValid, iterWrapperCount); +} + +template +typename TSLQueue::template TSLQIterWrapper TSLQueue::citer() { + return TSLQIterWrapper(&container, iterValid, iterWrapperCount); +} + +template +typename TSLQueue::template TSLQIterWrapper TSLQueue::criter() { + return TSLQIterWrapper(&container, iterValid, iterWrapperCount); +} + #endif