1#ifndef BTLLIB_ORDER_QUEUE_HPP 
    2#define BTLLIB_ORDER_QUEUE_HPP 
    6#include <condition_variable> 
   22    Block(
const size_t block_size)
 
   29      : current(block.current)
 
   33      std::swap(data, block.data);
 
   39    Block& operator=(
const Block& block) = 
default;
 
   43      std::swap(data, block.data);
 
   44      current = block.current;
 
   63    Slot(
size_t block_size)
 
   66    Slot(
const Slot& slot)
 
   68      , occupied(slot.occupied)
 
   69      , last_tenant(slot.last_tenant)
 
   71    Slot(Slot&& slot) noexcept
 
   73      , occupied(slot.occupied)
 
   74      , last_tenant(slot.last_tenant)
 
   77    Slot& operator=(
const Slot& slot)
 
   83      occupied = slot.occupied;
 
   84      last_tenant = slot.last_tenant;
 
   87    Slot& operator=(Slot&& slot) 
noexcept 
   90      occupied = slot.occupied;
 
   91      last_tenant = slot.last_tenant;
 
   95    typename OrderQueue<T>::Block block;
 
   97    bool occupied = 
false;
 
   98    std::condition_variable occupancy_changed;
 
   99    size_t last_tenant = -1; 
 
  102  size_t elements()
 const { 
return element_count; }
 
  106    bool closed_expected = 
false;
 
  107    if (closed.compare_exchange_strong(closed_expected, 
true)) {
 
  108      for (
auto& slot : this->slots) {
 
  109        std::unique_lock<std::mutex> busy_lock(slot.busy);
 
  110        slot.occupancy_changed.notify_all();
 
  115  bool is_closed()
 const { 
return closed; }
 
  117  OrderQueue(
const size_t queue_size, 
const size_t block_size)
 
  118    : slots(queue_size, Slot(block_size))
 
  119    , queue_size(queue_size)
 
  120    , block_size(block_size)
 
  123  OrderQueue(
const OrderQueue&) = 
delete;
 
  124  OrderQueue(OrderQueue&&) = 
delete;
 
  127  std::vector<Slot> slots;
 
  128  size_t queue_size, block_size;
 
  129  size_t read_counter = 0;
 
  130  std::atomic<size_t> element_count{ 0 };
 
  131  std::atomic<bool> closed{ 
false };
 
  134#define ORDER_QUEUE_XPXC(SUFFIX,                                               \ 
  136                         EXTRA_WRITE_LOCK_CONDS,                               \ 
  140                         EXTRA_READ_LOCK_CONDS,                                \ 
  144  template<typename T>                                                         \ 
  145  class OrderQueue##SUFFIX : public OrderQueue<T>                              \ 
  149    OrderQueue##SUFFIX(const size_t queue_size, const size_t block_size)       \ 
  150      : OrderQueue<T>(queue_size, block_size)                                  \ 
  153    using Block = typename OrderQueue<T>::Block;                               \ 
  154    using Slot = typename OrderQueue<T>::Slot;                                 \ 
  156    void write(Block& block)                                                   \ 
  159      const auto num = block.num;                                              \ 
  160      auto& target = this->slots[num % this->queue_size];                      \ 
  161      std::unique_lock<std::mutex> busy_lock(target.busy);                     \ 
  162      target.occupancy_changed.wait(busy_lock, [&] {                           \ 
  163        return (!target.occupied EXTRA_WRITE_LOCK_CONDS) || this->closed;      \ 
  165      if (this->closed) {                                                      \ 
  169      target.block = std::move(block);                                         \ 
  170      target.occupied = true;                                                  \ 
  171      target.occupancy_changed.NOTIFY_WRITE();                                 \ 
  172      ++(this->element_count);                                                 \ 
  175    void read(Block& block)                                                    \ 
  178      auto& target = this->slots[this->read_counter % this->queue_size];       \ 
  179      std::unique_lock<std::mutex> busy_lock(target.busy);                     \ 
  180      target.occupancy_changed.wait(busy_lock, [&] {                           \ 
  181        return (target.occupied EXTRA_READ_LOCK_CONDS) || this->closed;        \ 
  183      if (this->closed) {                                                      \ 
  186      ++(this->read_counter);                                                  \ 
  188      block = std::move(target.block);                                         \ 
  189      target.occupied = false;                                                 \ 
  190      target.occupancy_changed.NOTIFY_READ();                                  \ 
  191      --(this->element_count);                                                 \ 
  198ORDER_QUEUE_XPXC(SPSC, , , , notify_one, , , , notify_one, )
 
  199ORDER_QUEUE_XPXC(MPSC,
 
  201                 &&(num - target.last_tenant <= this->queue_size),
 
  202                 target.last_tenant = num,
 
  208ORDER_QUEUE_XPXC(SPMC,
 
  213                 std::unique_lock<std::mutex> read_lock(read_mutex),
 
  217                 std::mutex read_mutex;)
 
  218ORDER_QUEUE_XPXC(MPMC,
 
  220                 &&(num - target.last_tenant <= this->queue_size),
 
  221                 target.last_tenant = num,
 
  223                 std::unique_lock<std::mutex> read_lock(read_mutex),
 
  227                 std::mutex read_mutex;)
 
  229#undef ORDER_QUEUE_XPXC 
Definition: order_queue.hpp:16
Definition: bloom_filter.hpp:18
Definition: order_queue.hpp:20