cpp-ipc/include/circ_queue.h

112 lines
2.4 KiB
C++

#pragma once
#include <type_traits>
#include <new>
#include <exception>
#include <utility>
#include <algorithm>
#include "def.h"
#include "circ_elem_array.h"
namespace ipc {
namespace circ {
template <typename T>
class queue {
public:
using array_t = elem_array<sizeof(T)>;
private:
array_t* elems_ = nullptr;
typename std::result_of<decltype(&array_t::cursor)(array_t)>::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 <typename... P>
bool push(P&&... params) {
if (elems_ == nullptr) return false;
auto ptr = elems_->acquire();
::new (ptr) T { std::forward<P>(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<T*>(elems_->take(cursor_++));
T item = *item_ptr;
elems_->put(item_ptr);
return item;
}
};
} // namespace circ
} // namespace ipc