#pragma once #include #include #include #include #include #include "def.h" #include "circ_elem_array.h" namespace ipc { namespace circ { template class queue { public: using array_t = elem_array; private: array_t* elems_ = nullptr; typename std::result_of::type cursor_ = 0; bool connected_ = false; public: queue(void) = default; explicit queue(array_t* arr) : queue() { attach(arr); } queue(queue&& rhs) : queue() { swap(rhs); } void swap(queue& rhs) { std::swap(elems_ , rhs.elems_ ); std::swap(cursor_, rhs.cursor_); } queue& operator=(queue rhs) { swap(rhs); return *this; } array_t * elems(void) { return elems_; } std::size_t connect(void) { if (elems_ == nullptr) return error_count; if (connected_) return error_count; connected_ = true; return elems_->connect(); } std::size_t disconnect(void) { if (elems_ == nullptr) return error_count; if (!connected_) return error_count; connected_ = false; return elems_->disconnect(); } std::size_t conn_count(void) const { return (elems_ == nullptr) ? error_count : elems_->conn_count(); } bool connected(void) const { return connected_; } array_t* attach(array_t* arr) { if (arr == nullptr) return nullptr; auto old = elems_; elems_ = arr; cursor_ = elems_->cursor(); return old; } array_t* detach(void) { if (elems_ == nullptr) return nullptr; auto old = elems_; elems_ = nullptr; return old; } template bool push(P&&... params) { if (elems_ == nullptr) return false; auto ptr = elems_->acquire(); ::new (ptr) T { std::forward

(params)... }; elems_->commit(ptr); return true; } T pop(void) { if (elems_ == nullptr) throw std::invalid_argument { "This queue hasn't attached any elem_array." }; while (cursor_ == elems_->cursor()) { std::this_thread::yield(); } auto item_ptr = static_cast(elems_->take(cursor_++)); T item = *item_ptr; elems_->put(item_ptr); return item; } }; } // namespace circ } // namespace ipc