// // Created by Kirill Zhukov on 20.04.2025. // #ifndef SHAREDCOMMANDQUEUE_H #define SHAREDCOMMANDQUEUE_H #include "Command.h" #include "utils/datastructures/LFCircullarBuffer.h" #include #include namespace usub::core { constexpr size_t SHM_QUEUE_CAPACITY = 1024; class SharedCommandQueue { public: explicit SharedCommandQueue(size_t capacity); ~SharedCommandQueue(); bool try_push(const Command& cmd); bool try_push_batch(const Command* cmds, size_t count); void finalize(Command* cmd); std::optional try_pop(); size_t try_pop_batch(Command* out, size_t max_count); Command* peek(size_t index); void pop(); size_t pending_count() const; Command* raw_buffer() noexcept { return buffer_; } size_t capacity() const noexcept { return capacity_; } std::atomic& head() noexcept { return head_; } std::atomic& tail() noexcept { return tail_; } bool enqueue_put(const usub::utils::Hash128& key, const std::string& value) { size_t head = head_.load(std::memory_order_relaxed); size_t next_head = (head + 1) % capacity_; if (next_head == tail_.load(std::memory_order_acquire)) return false; Command& slot = buffer_[head]; slot.op = OperationType::PUT; slot.key = key; slot.value_size = static_cast(value.size()); std::memcpy(slot.value, value.data(), value.size()); slot.response_size = 0; slot.response_ready.store(0, std::memory_order_relaxed); slot.ready.store(1, std::memory_order_release); head_.store(next_head, std::memory_order_release); return true; } bool enqueue_find(const usub::utils::Hash128& key) { size_t head = head_.load(std::memory_order_relaxed); size_t next_head = (head + 1) % capacity_; if (next_head == tail_.load(std::memory_order_acquire)) return false; Command& slot = buffer_[head]; slot.op = OperationType::FIND; slot.key = key; slot.value_size = 0; slot.response_size = 0; slot.response_ready.store(0, std::memory_order_relaxed); slot.ready.store(1, std::memory_order_release); head_.store(next_head, std::memory_order_release); return true; } bool await_response(Command& cmd) { while (cmd.response_ready.load(std::memory_order_acquire) == 0) std::this_thread::sleep_for(std::chrono::milliseconds(1)); return cmd.response_size != 0; } private: size_t capacity_; Command* commands_; alignas(64) std::atomic head_; alignas(64) std::atomic tail_; alignas(64) Command buffer_[]; }; } #endif //SHAREDCOMMANDQUEUE_H