]> git.seodisparate.com - UDPConnection/commitdiff
Add impl of TSLQueue (TODO UnitTests)
authorStephen Seo <seo.disparate@gmail.com>
Thu, 24 Oct 2019 08:49:28 +0000 (17:49 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Thu, 24 Oct 2019 08:49:28 +0000 (17:49 +0900)
cpp_impl/src/TSLQueue.hpp

index 5a0253ad6ecbd8555fc2879fbffc05f4e8be7b2a..fd42df84ac9675d169319fab3d6e1fdab15e9f33 100644 (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