Add impl of TSLQueue (TODO UnitTests)
This commit is contained in:
parent
0402442929
commit
04d8abab84
1 changed files with 169 additions and 5 deletions
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -24,7 +26,9 @@ class TSLQueue {
|
||||||
TSLQueue &operator=(TSLQueue &&other);
|
TSLQueue &operator=(TSLQueue &&other);
|
||||||
|
|
||||||
bool push(const T &data);
|
bool push(const T &data);
|
||||||
|
bool push_nb(const T &data);
|
||||||
std::optional<T> top();
|
std::optional<T> top();
|
||||||
|
std::optional<T> top_nb();
|
||||||
bool pop();
|
bool pop();
|
||||||
std::optional<T> top_and_pop();
|
std::optional<T> top_and_pop();
|
||||||
std::optional<T> top_and_pop_and_empty(bool *isEmpty);
|
std::optional<T> top_and_pop_and_empty(bool *isEmpty);
|
||||||
|
@ -35,7 +39,11 @@ class TSLQueue {
|
||||||
template <bool isConst, bool isRev>
|
template <bool isConst, bool isRev>
|
||||||
class TSLQIterWrapper {
|
class TSLQIterWrapper {
|
||||||
public:
|
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;
|
bool isValid() const;
|
||||||
|
|
||||||
|
@ -56,16 +64,28 @@ class TSLQueue {
|
||||||
iter;
|
iter;
|
||||||
|
|
||||||
std::weak_ptr<void> iterValid;
|
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:
|
private:
|
||||||
std::shared_ptr<void> iterValid;
|
std::shared_ptr<void> iterValid;
|
||||||
|
std::shared_ptr<void> iterWrapperCount;
|
||||||
|
std::mutex mutex;
|
||||||
|
std::list<T> container;
|
||||||
};
|
};
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
TSLQueue<T>::TSLQueue() {
|
TSLQueue<T>::TSLQueue() :
|
||||||
|
iterValid(std::make_shared<void>()),
|
||||||
|
iterWrapperCount(std::make_shared<void>())
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -73,20 +93,144 @@ TSLQueue<T>::~TSLQueue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
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>
|
template <typename T>
|
||||||
TSLQueue<T> & TSLQueue<T>::operator=(TSLQueue &&other) {
|
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 <typename T>
|
||||||
template <bool isConst, bool isRev>
|
template <bool isConst, bool isRev>
|
||||||
TSLQueue<T>::TSLQIterWrapper<isConst, isRev>::TSLQIterWrapper(
|
TSLQueue<T>::TSLQIterWrapper<isConst, isRev>::TSLQIterWrapper(
|
||||||
std::conditional_t<isConst, const std::list<T>, std::list<T>> *container,
|
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),
|
containerPtr(container),
|
||||||
iterValid(iterValid) {
|
iterValid(iterValid),
|
||||||
|
iterWrapperCount(iterWrapperCount) {
|
||||||
if constexpr (isRev) {
|
if constexpr (isRev) {
|
||||||
if constexpr (isConst) {
|
if constexpr (isConst) {
|
||||||
iter = containerPtr->crbegin();
|
iter = containerPtr->crbegin();
|
||||||
|
@ -180,4 +324,24 @@ std::optional<T> TSLQueue<T>::TSLQIterWrapper<isConst, isRev>::current() {
|
||||||
return *iter;
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue