5#include <userver/engine/deadline.hpp> 
   14  template <
typename LockFreeQueue>
 
   15  explicit NoToken(LockFreeQueue& ) {}
 
   18struct MultiToken 
final {
 
   19  template <
typename LockFreeQueue>
 
   20  explicit MultiToken(LockFreeQueue& ) {}
 
   27template <
typename QueueType, 
typename ProducerToken,
 
   28          typename EmplaceEnablerType>
 
   31      std::is_same_v<EmplaceEnablerType, 
typename QueueType::EmplaceEnabler>,
 
   32      "Do not instantiate Producer on your own. Use Producer type alias " 
   35  using ValueType = 
typename QueueType::ValueType;
 
   38  Producer(
const Producer&) = 
delete;
 
   39  Producer(Producer&&) 
noexcept = 
default;
 
   40  Producer& operator=(
const Producer&) = 
delete;
 
   41  Producer& operator=(Producer&& other) 
noexcept {
 
   42    queue_.swap(other.queue_);
 
   43    std::swap(token_, other.token_);
 
   48    if (queue_) queue_->MarkProducerIsDead();
 
   55  [[nodiscard]] 
bool Push(ValueType&& value,
 
   56                          engine::Deadline deadline 
= {}) 
const {
 
   58    return queue_->Push(token_, std::move(value), deadline);
 
   65  [[nodiscard]] 
bool PushNoblock(ValueType&& value) 
const {
 
   67    return queue_->PushNoblock(token_, std::move(value));
 
   71    if (queue_) queue_->MarkProducerIsDead();
 
   73    [[maybe_unused]] ProducerToken for_destruction = std::move(token_);
 
   77  [[nodiscard]] std::shared_ptr<
const QueueType> 
Queue() 
const {
 
   83  Producer(std::shared_ptr<QueueType> queue, EmplaceEnablerType )
 
   84      : queue_(std::move(queue)), token_(queue_->queue_) {}
 
   88  std::shared_ptr<QueueType> queue_;
 
   89  mutable ProducerToken token_;
 
   94template <
typename QueueType, 
typename ConsumerToken,
 
   95          typename EmplaceEnablerType>
 
   98      std::is_same_v<EmplaceEnablerType, 
typename QueueType::EmplaceEnabler>,
 
   99      "Do not instantiate Consumer on your own. Use Consumer type alias " 
  102  using ValueType = 
typename QueueType::ValueType;
 
  105  Consumer(
const Consumer&) = 
delete;
 
  106  Consumer(Consumer&&) 
noexcept = 
default;
 
  107  Consumer& operator=(
const Consumer&) = 
delete;
 
  108  Consumer& operator=(Consumer&& other) 
noexcept {
 
  109    queue_.swap(other.queue_);
 
  110    std::swap(token_, other.token_);
 
  115    if (queue_) queue_->MarkConsumerIsDead();
 
  123  [[nodiscard]] 
bool Pop(ValueType& value,
 
  124                         engine::Deadline deadline 
= {}) 
const {
 
  125    return queue_->Pop(token_, value, deadline);
 
  131  [[nodiscard]] 
bool PopNoblock(ValueType& value) 
const {
 
  132    return queue_->PopNoblock(token_, value);
 
  136    if (queue_) queue_->MarkConsumerIsDead();
 
  138    [[maybe_unused]] ConsumerToken for_destruction = std::move(token_);
 
  142  [[nodiscard]] std::shared_ptr<
const QueueType> 
Queue() 
const {
 
  148  Consumer(std::shared_ptr<QueueType> queue, EmplaceEnablerType )
 
  149      : queue_(std::move(queue)), token_(queue_->queue_) {}
 
  153  std::shared_ptr<QueueType> queue_{};
 
  154  mutable ConsumerToken token_;