From f7f3bcfcdd12654d81082df2a28870c44fcb85ca Mon Sep 17 00:00:00 2001 From: FritzFlorian Date: Mon, 1 Apr 2019 11:08:08 +0200 Subject: [PATCH] Add basic deque implementation. This implementation allows one to add the deque_item property to any class and then manage pointers to these items in a deque. We currently use a spinlock for concurrent access. --- lib/pls/CMakeLists.txt | 4 ++-- lib/pls/include/pls/internal/base/deque.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pls/src/internal/base/deque.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 lib/pls/include/pls/internal/base/deque.h create mode 100644 lib/pls/src/internal/base/deque.cpp diff --git a/lib/pls/CMakeLists.txt b/lib/pls/CMakeLists.txt index bba3227..bad2b80 100644 --- a/lib/pls/CMakeLists.txt +++ b/lib/pls/CMakeLists.txt @@ -1,6 +1,6 @@ # List all required files here (cmake best practice to NOT automate this step!) add_library(pls STATIC - src/library.cpp include/pls/library.h + src/pls.cpp include/pls/pls.h src/internal/base/spin_lock.cpp include/pls/internal/base/spin_lock.h src/internal/base/thread.cpp include/pls/internal/base/thread.h include/pls/internal/base/prohibit_new.h @@ -13,7 +13,7 @@ add_library(pls STATIC include/pls/internal/base/system_details.h src/internal/scheduling/run_on_n_threads_task.cpp include/pls/internal/scheduling/run_on_n_threads_task.h src/internal/scheduling/tbb_task.cpp include/pls/internal/scheduling/tbb_task.h - ) + src/internal/base/deque.cpp include/pls/internal/base/deque.h) # Add everything in `./include` to be in the include path of this project target_include_directories(pls diff --git a/lib/pls/include/pls/internal/base/deque.h b/lib/pls/include/pls/internal/base/deque.h new file mode 100644 index 0000000..5fbe0bb --- /dev/null +++ b/lib/pls/include/pls/internal/base/deque.h @@ -0,0 +1,51 @@ + +#ifndef PLS_DEQUE_H +#define PLS_DEQUE_H + +#include "spin_lock.h" + +namespace pls { + namespace internal { + namespace base { + class deque_item { + friend class deque_internal; + + deque_item* prev_; + deque_item* next_; + + }; + + class deque_internal { + protected: + deque_item* head_; + deque_item* tail_; + + spin_lock lock_; + + deque_item* pop_head_internal(); + deque_item* pop_tail_internal(); + void push_tail_internal(deque_item *new_item); + }; + + template + class deque: deque_internal { + public: + explicit deque(): deque_internal{} {} + + inline Item* pop_head() { + return static_cast(pop_head_internal()); + } + + inline Item* pop_tail() { + return static_cast(pop_tail_internal()); + } + + inline void push_tail(Item* new_item) { + push_tail_internal(new_item); + } + }; + } + } +} + +#endif //PLS_DEQUE_H diff --git a/lib/pls/src/internal/base/deque.cpp b/lib/pls/src/internal/base/deque.cpp new file mode 100644 index 0000000..5370a91 --- /dev/null +++ b/lib/pls/src/internal/base/deque.cpp @@ -0,0 +1,58 @@ +#include + +#include "pls/internal/base/deque.h" + +namespace pls { + namespace internal { + namespace base { + deque_item* deque_internal::pop_head_internal() { + std::lock_guard lock{lock_}; + + if (head_ == nullptr) { + return nullptr; + } + + deque_item* result = head_; + head_ = head_->prev_; + if (head_ == nullptr) { + tail_ = nullptr; + } else { + head_->next_ = nullptr; + } + + return result; + } + + deque_item* deque_internal::pop_tail_internal() { + std::lock_guard lock{lock_}; + + if (tail_ == nullptr) { + return nullptr; + } + + deque_item* result = tail_; + tail_ = tail_->next_; + if (tail_ == nullptr) { + head_ = nullptr; + } else { + tail_->prev_ = nullptr; + } + + return result; + } + + void deque_internal::push_tail_internal(deque_item *new_item) { + std::lock_guard lock{lock_}; + + if (tail_ != nullptr) { + tail_->prev_ = new_item; + } else { + head_ = new_item; + } + new_item->next_ = tail_; + new_item->prev_ = nullptr; + tail_ = new_item; + } + } + } +} -- libgit2 0.26.0