123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- #pragma once
- #include "message.hpp"
- #include <cassert>
- #include <cstddef>
- #include <limits>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- namespace rotor_light {
- struct ItemQueueBase;
- struct ItemGuard {
- ItemGuard() : message{nullptr} {}
-
- ItemGuard(Message *message_, ItemQueueBase *item_queue_)
- : message{message_}, item_queue{item_queue_} {}
- ItemGuard(const ItemGuard &) = delete;
- ItemGuard(ItemGuard &&) = delete;
-
- ItemGuard &operator=(const ItemGuard &) = default;
-
- inline operator bool() { return message; }
-
- inline Message &operator*() { return *message; }
-
- Message *message;
-
- ItemQueueBase *item_queue;
- };
- struct ItemQueueBase {
-
- ItemQueueBase(size_t item_size, size_t items_count);
- ItemQueueBase(const ItemQueueBase &) = delete;
- ItemQueueBase(ItemQueueBase &&) = delete;
-
- Message *next();
-
- template <typename MessageType, bool force, typename... Args>
- bool put(Args &&...args) {
- static_assert(std::is_base_of<Message, MessageType>::value,
- "type should be inherited from Message");
- assert((sizeof(MessageType) <= item_size) &&
- "no storage for the message, increase ItemSize");
- bool full = (items_size == items_count);
- bool r;
- if constexpr (!force) {
- if (full) {
- return false;
- }
- auto ptr = buff_ptr + item_size * free_index;
- if (free_index == items_size - 1) {
- free_index = 0;
- } else {
- ++free_index;
- }
- auto message = new (ptr) MessageType(std::forward<Args>(args)...);
- message->type = MessageType::type_id;
- ++items_count;
- r = true;
- } else {
- auto ptr = buff_ptr + item_size * free_index;
- if (!full) {
- ++items_count;
- if (free_index == items_size - 1) {
- free_index = 0;
- } else {
- ++free_index;
- }
- } else {
- ++free_index;
- if (occupied_index + 1 == items_size) {
- occupied_index = 0;
- } else {
- ++occupied_index;
- }
- }
- auto message = new (ptr) MessageType(std::forward<Args>(args)...);
- message->type = MessageType::type_id;
- r = full;
- }
- #ifdef ROTOR_LIGHT_QUEUE_SZ
- if (items_count_maxinum < items_count) {
- items_count_maxinum = items_count;
- }
- #endif
- return r;
- }
- #ifdef ROTOR_LIGHT_QUEUE_SZ
-
- Index max_items() const;
- #endif
-
- void release();
-
- template <typename T> auto &access() noexcept;
- protected:
- friend struct Message;
-
- void post_constructor(char *buff);
- private:
- char *buff_ptr;
- Index item_size;
- Index items_size;
- Index items_count;
- Index free_index;
- Index occupied_index;
- #ifdef ROTOR_LIGHT_QUEUE_SZ
- Index items_count_maxinum;
- #endif
- };
- template <typename Storage, size_t ItemsCount>
- struct ItemQueue : ItemQueueBase {
- static_assert(Storage::item_size > 0, "queue size have to be positive");
- ItemQueue() : ItemQueueBase(Storage::item_size, ItemsCount) {
- post_constructor(reinterpret_cast<char *>(&storage));
- }
- private:
- using Item = typename Storage::Item;
- Item storage[ItemsCount];
- };
- struct QueueBase {
-
- QueueBase(ItemQueueBase **queues, size_t queue_count);
- QueueBase(const QueueBase &) = delete;
- QueueBase(QueueBase &&) = delete;
-
- template <typename MessageType, bool force, typename... Args>
- bool put(Index queue_index, Args &&...args) {
- assert((queue_index < queue_count) && "valid queue/priority");
- auto &queue = queues[queue_index];
- return queue->put<MessageType, force>(std::forward<Args>(args)...);
- }
- #ifdef ROTOR_LIGHT_QUEUE_SZ
-
- Index max_items(Index queue_index) const;
- #endif
-
- ItemGuard next();
-
- template <typename T> auto &access() noexcept;
- private:
- ItemQueueBase **queues;
- uint8_t queue_count;
- };
- template <typename Storage, size_t... Counts> struct Queue : QueueBase {
- static_assert(Storage::item_size > sizeof(Message),
- "not enough storage for a message");
-
- using Queues = std::tuple<ItemQueue<Storage, Counts>...>;
-
- static constexpr size_t Size = std::tuple_size<Queues>::value;
- static_assert(Size > 0, "there should be at least one queue");
- Queue() : QueueBase(queues, Size) { fill_queue<0>(); }
- private:
- template <Index Index> void fill_queue() {
- auto &queue = std::get<Index>(queues_storage);
- queues[Index] = &queue;
- if constexpr (Index + 1 < Size) {
- fill_queue<Index + 1>();
- }
- }
- Queues queues_storage;
- ItemQueueBase *queues[Size];
- };
- }
|