proxygen
folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom > Class Template Reference

#include <UnboundedQueue.h>

Classes

struct  Consumer
 
class  Entry
 
struct  Producer
 
class  Segment
 

Public Member Functions

 UnboundedQueue ()
 
 ~UnboundedQueue ()
 
FOLLY_ALWAYS_INLINE void enqueue (const T &arg)
 
FOLLY_ALWAYS_INLINE void enqueue (T &&arg)
 
FOLLY_ALWAYS_INLINE void dequeue (T &item) noexcept
 
FOLLY_ALWAYS_INLINE bool try_dequeue (T &item) noexcept
 
FOLLY_ALWAYS_INLINE folly::Optional< Ttry_dequeue () noexcept
 
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE bool try_dequeue_until (T &item, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
 
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE folly::Optional< Ttry_dequeue_until (const std::chrono::time_point< Clock, Duration > &deadline) noexcept
 
template<typename Rep , typename Period >
FOLLY_ALWAYS_INLINE bool try_dequeue_for (T &item, const std::chrono::duration< Rep, Period > &duration) noexcept
 
template<typename Rep , typename Period >
FOLLY_ALWAYS_INLINE folly::Optional< Ttry_dequeue_for (const std::chrono::duration< Rep, Period > &duration) noexcept
 
FOLLY_ALWAYS_INLINE const Ttry_peek () noexcept
 
size_t size () const noexcept
 
bool empty () const noexcept
 

Private Types

using Ticket = uint64_t
 

Private Member Functions

template<typename Arg >
FOLLY_ALWAYS_INLINE void enqueueImpl (Arg &&arg)
 
template<typename Arg >
FOLLY_ALWAYS_INLINE void enqueueCommon (Segment *s, Arg &&arg)
 
FOLLY_ALWAYS_INLINE void dequeueImpl (T &item) noexcept
 
FOLLY_ALWAYS_INLINE void dequeueCommon (Segment *s, T &item) noexcept
 
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE folly::Optional< TtryDequeueUntil (const std::chrono::time_point< Clock, Duration > &deadline) noexcept
 
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE folly::Optional< TtryDequeueUntilSC (Segment *s, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
 
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE folly::Optional< TtryDequeueUntilMC (Segment *s, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
 
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE bool tryDequeueWaitElem (Entry &e, Ticket t, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
 
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE const TtryPeekUntil (const std::chrono::time_point< Clock, Duration > &deadline) noexcept
 
FOLLY_ALWAYS_INLINE SegmentfindSegment (Segment *s, const Ticket t) noexcept
 
SegmentgetAllocNextSegment (Segment *s, Ticket t) noexcept
 
SegmentallocNextSegment (Segment *s)
 
void advanceTail (Segment *s) noexcept
 
void advanceTailToTicket (Ticket t) noexcept
 
void advanceHead (Segment *s) noexcept
 
void advanceHeadToTicket (Ticket t) noexcept
 
void reclaimSegment (Segment *s) noexcept
 
void cleanUpRemainingItems ()
 
void reclaimRemainingSegments ()
 
FOLLY_ALWAYS_INLINE size_t index (Ticket t) const noexcept
 
FOLLY_ALWAYS_INLINE bool responsibleForAlloc (Ticket t) const noexcept
 
FOLLY_ALWAYS_INLINE bool responsibleForAdvance (Ticket t) const noexcept
 
FOLLY_ALWAYS_INLINE Segmenthead () const noexcept
 
FOLLY_ALWAYS_INLINE Segmenttail () const noexcept
 
FOLLY_ALWAYS_INLINE Ticket producerTicket () const noexcept
 
FOLLY_ALWAYS_INLINE Ticket consumerTicket () const noexcept
 
void setHead (Segment *s) noexcept
 
void setTail (Segment *s) noexcept
 
bool casHead (Segment *&s, Segment *next) noexcept
 
void casTail (Segment *&s, Segment *next) noexcept
 
FOLLY_ALWAYS_INLINE void setProducerTicket (Ticket t) noexcept
 
FOLLY_ALWAYS_INLINE void setConsumerTicket (Ticket t) noexcept
 
FOLLY_ALWAYS_INLINE Ticket fetchIncrementConsumerTicket () noexcept
 
FOLLY_ALWAYS_INLINE Ticket fetchIncrementProducerTicket () noexcept
 

Private Attributes

Consumer c_
 
Producer p_
 

Static Private Attributes

static constexpr bool SPSC = SingleProducer && SingleConsumer
 
static constexpr size_t Stride = SPSC || (LgSegmentSize <= 1) ? 1 : 27
 
static constexpr size_t SegmentSize = 1u << LgSegmentSize
 
static constexpr size_t Align = 1u << LgAlign
 

Detailed Description

template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
class folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >

UnboundedQueue supports a variety of options for unbounded dynamically expanding an shrinking queues, including variations of:

  • Single vs. multiple producers
  • Single vs. multiple consumers
  • Blocking vs. spin-waiting
  • Non-waiting, timed, and waiting consumer operations. Producer operations never wait or fail (unless out-of-memory).

Template parameters:

  • T: element type
  • SingleProducer: true if there can be only one producer at a time.
  • SingleConsumer: true if there can be only one consumer at a time.
  • MayBlock: true if consumers may block, false if they only spin. A performance tuning parameter.
  • LgSegmentSize (default 8): Log base 2 of number of elements per segment. A performance tuning parameter. See below.
  • LgAlign (default 7): Log base 2 of alignment directive; can be used to balance scalability (avoidance of false sharing) with memory efficiency.

When to use UnboundedQueue:

  • If a small bound may lead to deadlock or performance degradation under bursty patterns.
  • If there is no risk of the queue growing too much.

When not to use UnboundedQueue:

  • If there is risk of the queue growing too much and a large bound is acceptable, then use DynamicBoundedQueue.
  • If the queue must not allocate on enqueue or it must have a small bound, then use fixed-size MPMCQueue or (if non-blocking SPSC) ProducerConsumerQueue.

Template Aliases: USPSCQueue<T, MayBlock, LgSegmentSize, LgAlign> UMPSCQueue<T, MayBlock, LgSegmentSize, LgAlign> USPMCQueue<T, MayBlock, LgSegmentSize, LgAlign> UMPMCQueue<T, MayBlock, LgSegmentSize, LgAlign>

Functions: Producer operations never wait or fail (unless OOM) void enqueue(const T&); void enqueue(T&&); Adds an element to the end of the queue.

Consumer operations: void dequeue(T&); Extracts an element from the front of the queue. Waits until an element is available if needed. bool try_dequeue(T&); folly::Optional<T> try_dequeue(); Tries to extract an element from the front of the queue if available. bool try_dequeue_until(T&, time_point& deadline); folly::Optional<T> try_dequeue_until(time_point& deadline); Tries to extract an element from the front of the queue if available until the specified deadline. bool try_dequeue_for(T&, duration&); folly::Optional<T> try_dequeue_for(duration&); Tries to extract an element from the front of the queue if available until the expiration of the specified duration. const T* try_peek(); Returns pointer to the element at the front of the queue if available, or nullptr if the queue is empty. Only for SPSC and MPSC.

Secondary functions: size_t size(); Returns an estimate of the size of the queue. bool empty(); Returns true only if the queue was empty during the call. Note: size() and empty() are guaranteed to be accurate only if the queue is not changed concurrently.

Usage examples:

/* UMPSC, doesn't block, 1024 int elements per segment */
UMPSCQueue<int, false, 10> q;
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
ASSERT_FALSE(q.empty());
ASSERT_EQ(q.size(), 3);
int v;
q.dequeue(v);
ASSERT_EQ(v, 1);
ASSERT_EQ(v, 2);
ASSERT_TRUE(try_dequeue_until(v, now() + seconds(1)));
ASSERT_EQ(v, 3);
ASSERT_TRUE(q.empty());
ASSERT_EQ(q.size(), 0);
ASSERT_FALSE(try_dequeue_for(v, microseconds(100)));

Design:

  • The queue is composed of one or more segments. Each segment has a fixed size of 2^LgSegmentSize entries. Each segment is used exactly once.
  • Each entry is composed of a futex and a single element.
  • The queue contains two 64-bit ticket variables. The producer ticket counts the number of producer tickets issued so far, and the same for the consumer ticket. Each ticket number corresponds to a specific entry in a specific segment.
  • The queue maintains two pointers, head and tail. Head points to the segment that corresponds to the current consumer ticket. Similarly, tail pointer points to the segment that corresponds to the producer ticket.
  • Segments are organized as a singly linked list.
  • The producer with the first ticket in the current producer segment has primary responsibility for allocating and linking the next segment. Other producers and connsumers may help do so when needed if that thread is delayed.
  • The producer with the last ticket in the current producer segment is primarily responsible for advancing the tail pointer to the next segment. Other producers and consumers may help do so when needed if that thread is delayed.
  • Similarly, the consumer with the last ticket in the current consumer segment is primarily responsible for advancing the head pointer to the next segment. Other consumers may help do so when needed if that thread is delayed.
  • The tail pointer must not lag behind the head pointer. Otherwise, the algorithm cannot be certain about the removal of segment and would have to incur higher costs to ensure safe reclamation. Consumers must ensure that head never overtakes tail.

Memory Usage:

  • An empty queue contains one segment. A nonempty queue contains one or two more segment than fits its contents.
  • Removed segments are not reclaimed until there are no threads, producers or consumers, with references to them or their predecessors. That is, a lagging thread may delay the reclamation of a chain of removed segments.
  • The template parameter LgAlign can be used to reduce memory usage at the cost of increased chance of false sharing.

Performance considerations:

  • All operations take constant time, excluding the costs of allocation, reclamation, interference from other threads, and waiting for actions by other threads.
  • In general, using the single producer and or single consumer variants yield better performance than the MP and MC alternatives.
  • SPSC without blocking is the fastest configuration. It doesn't include any read-modify-write atomic operations, full fences, or system calls in the critical path.
  • MP adds a fetch_add to the critical path of each producer operation.
  • MC adds a fetch_add or compare_exchange to the critical path of each consumer operation.
  • The possibility of consumers blocking, even if they never do, adds a compare_exchange to the critical path of each producer operation.
  • MPMC, SPMC, MPSC require the use of a deferred reclamation mechanism to guarantee that segments removed from the linked list, i.e., unreachable from the head pointer, are reclaimed only after they are no longer needed by any lagging producers or consumers.
  • The overheads of segment allocation and reclamation are intended to be mostly out of the critical path of the queue's throughput.
  • If the template parameter LgSegmentSize is changed, it should be set adequately high to keep the amortized cost of allocation and reclamation low.
  • It is recommended to measure performance with different variants when applicable, e.g., UMPMC vs UMPSC. Depending on the use case, sometimes the variant with the higher sequential overhead may yield better results due to, for example, more favorable producer-consumer balance or favorable timing for avoiding costly blocking.

Definition at line 216 of file UnboundedQueue.h.

Member Typedef Documentation

template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
using folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::Ticket = uint64_t
private

Definition at line 217 of file UnboundedQueue.h.

Constructor & Destructor Documentation

template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::UnboundedQueue ( )
inline

constructor

Definition at line 249 of file UnboundedQueue.h.

250  : c_(new Segment(0)), p_(c_.head.load(std::memory_order_relaxed)) {}
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::~UnboundedQueue ( )
inline

destructor

Definition at line 253 of file UnboundedQueue.h.

253  {
256  }

Member Function Documentation

template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::advanceHead ( Segment s)
inlineprivatenoexcept

advanceHead

Definition at line 586 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::dequeueCommon(), folly::UnboundedQueue< T, false, 6 >::tryDequeueUntilMC(), and folly::UnboundedQueue< T, false, 6 >::tryDequeueUntilSC().

586  {
587  if (SPSC) {
588  while (tail() == s) {
589  /* Wait for producer to advance tail. */
591  }
592  Segment* next = s->nextSegment();
593  DCHECK(next);
594  setHead(next);
595  reclaimSegment(s);
596  } else {
597  Ticket t = s->minTicket() + SegmentSize;
599  }
600  }
void setHead(Segment *s) noexcept
void advanceHeadToTicket(Ticket t) noexcept
static constexpr size_t SegmentSize
void reclaimSegment(Segment *s) noexcept
FOLLY_ALWAYS_INLINE Segment * tail() const noexcept
static set< string > s
static constexpr bool SPSC
def next(obj)
Definition: ast.py:58
void asm_volatile_pause()
Definition: Asm.h:37
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::advanceHeadToTicket ( Ticket  t)
inlineprivatenoexcept

advanceHeadToTicket

Definition at line 603 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::advanceHead().

603  {
604  /* Tail must not lag behind head. Otherwise, the algorithm cannot
605  be certain about removal of segments. */
607  Segment* s = head();
608  if (SingleConsumer) {
609  DCHECK_EQ(s->minTicket() + SegmentSize, t);
610  Segment* next = s->nextSegment();
611  DCHECK(next);
612  setHead(next);
613  reclaimSegment(s);
614  } else {
615  while (s->minTicket() < t) {
616  Segment* next = s->nextSegment();
617  DCHECK(next);
618  if (casHead(s, next)) {
619  reclaimSegment(s);
620  s = next;
621  }
622  }
623  }
624  }
void setHead(Segment *s) noexcept
bool casHead(Segment *&s, Segment *next) noexcept
static constexpr size_t SegmentSize
void reclaimSegment(Segment *s) noexcept
void advanceTailToTicket(Ticket t) noexcept
FOLLY_ALWAYS_INLINE Segment * head() const noexcept
static set< string > s
def next(obj)
Definition: ast.py:58
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::advanceTail ( Segment s)
inlineprivatenoexcept

advanceTail

Definition at line 560 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::enqueueCommon().

560  {
561  if (SPSC) {
562  Segment* next = s->nextSegment();
563  DCHECK(next);
564  setTail(next);
565  } else {
566  Ticket t = s->minTicket() + SegmentSize;
568  }
569  }
void setTail(Segment *s) noexcept
static constexpr size_t SegmentSize
void advanceTailToTicket(Ticket t) noexcept
static set< string > s
static constexpr bool SPSC
def next(obj)
Definition: ast.py:58
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::advanceTailToTicket ( Ticket  t)
inlineprivatenoexcept

advanceTailToTicket

Definition at line 572 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::advanceHeadToTicket(), and folly::UnboundedQueue< T, false, 6 >::advanceTail().

572  {
573  Segment* s = tail();
574  while (s->minTicket() < t) {
575  Segment* next = s->nextSegment();
576  if (!next) {
577  next = allocNextSegment(s);
578  }
579  DCHECK(next);
580  casTail(s, next);
581  s = tail();
582  }
583  }
Segment * allocNextSegment(Segment *s)
FOLLY_ALWAYS_INLINE Segment * tail() const noexcept
static set< string > s
void casTail(Segment *&s, Segment *next) noexcept
def next(obj)
Definition: ast.py:58
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
Segment* folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::allocNextSegment ( Segment s)
inlineprivate

allocNextSegment

Definition at line 547 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::advanceTailToTicket(), folly::UnboundedQueue< T, false, 6 >::enqueueCommon(), and folly::UnboundedQueue< T, false, 6 >::getAllocNextSegment().

547  {
548  auto t = s->minTicket() + SegmentSize;
549  Segment* next = new Segment(t);
550  next->acquire_ref_safe(); // defined in hazptr_obj_base_linked
551  if (!s->casNextSegment(next)) {
552  delete next;
553  next = s->nextSegment();
554  }
555  DCHECK(next);
556  return next;
557  }
static constexpr size_t SegmentSize
static set< string > s
def next(obj)
Definition: ast.py:58
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::casHead ( Segment *&  s,
Segment next 
)
inlineprivatenoexcept

Definition at line 701 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::advanceHeadToTicket().

701  {
702  DCHECK(!SingleConsumer);
703  return c_.head.compare_exchange_strong(
704  s, next, std::memory_order_release, std::memory_order_acquire);
705  }
static set< string > s
def next(obj)
Definition: ast.py:58
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::casTail ( Segment *&  s,
Segment next 
)
inlineprivatenoexcept

Definition at line 707 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::advanceTailToTicket().

707  {
708  DCHECK(!SPSC);
709  p_.tail.compare_exchange_strong(
710  s, next, std::memory_order_release, std::memory_order_relaxed);
711  }
static set< string > s
static constexpr bool SPSC
def next(obj)
Definition: ast.py:58
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::cleanUpRemainingItems ( )
inlineprivate

cleanUpRemainingItems

Definition at line 636 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::~UnboundedQueue().

636  {
637  auto end = producerTicket();
638  auto s = head();
639  for (auto t = consumerTicket(); t < end; ++t) {
640  if (t >= s->minTicket() + SegmentSize) {
641  s = s->nextSegment();
642  }
643  DCHECK_LT(t, (s->minTicket() + SegmentSize));
644  auto idx = index(t);
645  auto& e = s->entry(idx);
646  e.destroyItem();
647  }
648  }
FOLLY_ALWAYS_INLINE Ticket consumerTicket() const noexcept
auto end(TestAdlIterable &instance)
Definition: ForeachTest.cpp:62
static constexpr size_t SegmentSize
FOLLY_ALWAYS_INLINE size_t index(Ticket t) const noexcept
FOLLY_ALWAYS_INLINE Segment * head() const noexcept
static set< string > s
FOLLY_ALWAYS_INLINE Ticket producerTicket() const noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE Ticket folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::consumerTicket ( ) const
inlineprivatenoexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::dequeue ( T item)
inlinenoexcept

dequeue

Definition at line 268 of file UnboundedQueue.h.

Referenced by enq_deq_test().

268  {
269  dequeueImpl(item);
270  }
FOLLY_ALWAYS_INLINE void dequeueImpl(T &item) noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::dequeueCommon ( Segment s,
T item 
)
inlineprivatenoexcept

dequeueCommon

Definition at line 405 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::dequeueImpl().

405  {
407  if (!SingleConsumer) {
408  s = findSegment(s, t);
409  }
410  size_t idx = index(t);
411  Entry& e = s->entry(idx);
412  e.takeItem(item);
413  if (responsibleForAdvance(t)) {
414  advanceHead(s);
415  }
416  }
FOLLY_ALWAYS_INLINE Segment * findSegment(Segment *s, const Ticket t) noexcept
FOLLY_ALWAYS_INLINE bool responsibleForAdvance(Ticket t) const noexcept
FOLLY_ALWAYS_INLINE Ticket fetchIncrementConsumerTicket() noexcept
FOLLY_ALWAYS_INLINE size_t index(Ticket t) const noexcept
static set< string > s
void advanceHead(Segment *s) noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::dequeueImpl ( T item)
inlineprivatenoexcept

dequeueImpl

Definition at line 390 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::dequeue().

390  {
391  if (SPSC) {
392  Segment* s = head();
393  dequeueCommon(s, item);
394  } else {
395  // Using hazptr_holder instead of hazptr_local because it is
396  // possible to call the T dtor and it may happen to use hazard
397  // pointers.
398  hazptr_holder<Atom> hptr;
399  Segment* s = hptr.get_protected(c_.head);
400  dequeueCommon(s, item);
401  }
402  }
FOLLY_ALWAYS_INLINE void dequeueCommon(Segment *s, T &item) noexcept
FOLLY_ALWAYS_INLINE Segment * head() const noexcept
static set< string > s
static constexpr bool SPSC
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::empty ( ) const
inlinenoexcept

empty

Definition at line 347 of file UnboundedQueue.h.

347  {
348  auto c = consumerTicket();
349  auto p = producerTicket();
350  return p <= c;
351  }
FOLLY_ALWAYS_INLINE Ticket consumerTicket() const noexcept
FOLLY_ALWAYS_INLINE Ticket producerTicket() const noexcept
char c
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::enqueue ( const T arg)
inline

enqueue

Definition at line 259 of file UnboundedQueue.h.

Referenced by enq_deq_test(), and TEST().

259  {
260  enqueueImpl(arg);
261  }
FOLLY_ALWAYS_INLINE void enqueueImpl(Arg &&arg)
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::enqueue ( T &&  arg)
inline

Definition at line 263 of file UnboundedQueue.h.

263  {
264  enqueueImpl(std::move(arg));
265  }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
FOLLY_ALWAYS_INLINE void enqueueImpl(Arg &&arg)
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Arg >
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::enqueueCommon ( Segment s,
Arg &&  arg 
)
inlineprivate

enqueueCommon

Definition at line 371 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::enqueueImpl().

371  {
373  if (!SingleProducer) {
374  s = findSegment(s, t);
375  }
376  DCHECK_GE(t, s->minTicket());
377  DCHECK_LT(t, s->minTicket() + SegmentSize);
378  size_t idx = index(t);
379  Entry& e = s->entry(idx);
380  e.putItem(std::forward<Arg>(arg));
381  if (responsibleForAlloc(t)) {
383  }
384  if (responsibleForAdvance(t)) {
385  advanceTail(s);
386  }
387  }
FOLLY_ALWAYS_INLINE Segment * findSegment(Segment *s, const Ticket t) noexcept
FOLLY_ALWAYS_INLINE bool responsibleForAdvance(Ticket t) const noexcept
Segment * allocNextSegment(Segment *s)
void advanceTail(Segment *s) noexcept
FOLLY_ALWAYS_INLINE bool responsibleForAlloc(Ticket t) const noexcept
static constexpr size_t SegmentSize
FOLLY_ALWAYS_INLINE size_t index(Ticket t) const noexcept
static set< string > s
FOLLY_ALWAYS_INLINE Ticket fetchIncrementProducerTicket() noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Arg >
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::enqueueImpl ( Arg &&  arg)
inlineprivate

enqueueImpl

Definition at line 356 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::enqueue().

356  {
357  if (SPSC) {
358  Segment* s = tail();
359  enqueueCommon(s, std::forward<Arg>(arg));
360  } else {
361  // Using hazptr_holder instead of hazptr_local because it is
362  // possible that the T ctor happens to use hazard pointers.
363  hazptr_holder<Atom> hptr;
364  Segment* s = hptr.get_protected(p_.tail);
365  enqueueCommon(s, std::forward<Arg>(arg));
366  }
367  }
FOLLY_ALWAYS_INLINE Segment * tail() const noexcept
static set< string > s
static constexpr bool SPSC
FOLLY_ALWAYS_INLINE void enqueueCommon(Segment *s, Arg &&arg)
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE Ticket folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::fetchIncrementConsumerTicket ( )
inlineprivatenoexcept

Definition at line 721 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::dequeueCommon().

721  {
722  if (SingleConsumer) {
723  Ticket oldval = consumerTicket();
724  setConsumerTicket(oldval + 1);
725  return oldval;
726  } else { // MC
727  return c_.ticket.fetch_add(1, std::memory_order_acq_rel);
728  }
729  }
FOLLY_ALWAYS_INLINE Ticket consumerTicket() const noexcept
FOLLY_ALWAYS_INLINE void setConsumerTicket(Ticket t) noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE Ticket folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::fetchIncrementProducerTicket ( )
inlineprivatenoexcept

Definition at line 731 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::enqueueCommon().

731  {
732  if (SingleProducer) {
733  Ticket oldval = producerTicket();
734  setProducerTicket(oldval + 1);
735  return oldval;
736  } else { // MP
737  return p_.ticket.fetch_add(1, std::memory_order_acq_rel);
738  }
739  }
FOLLY_ALWAYS_INLINE void setProducerTicket(Ticket t) noexcept
FOLLY_ALWAYS_INLINE Ticket producerTicket() const noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE Segment* folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::findSegment ( Segment s,
const Ticket  t 
)
inlineprivatenoexcept

findSegment

Definition at line 514 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::dequeueCommon(), and folly::UnboundedQueue< T, false, 6 >::enqueueCommon().

514  {
515  while (UNLIKELY(t >= (s->minTicket() + SegmentSize))) {
516  s = getAllocNextSegment(s, t);
517  DCHECK(s);
518  }
519  return s;
520  }
Segment * getAllocNextSegment(Segment *s, Ticket t) noexcept
static constexpr size_t SegmentSize
static set< string > s
#define UNLIKELY(x)
Definition: Likely.h:48
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
Segment* folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::getAllocNextSegment ( Segment s,
Ticket  t 
)
inlineprivatenoexcept

getAllocNextSegment

Definition at line 523 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::findSegment(), and folly::UnboundedQueue< T, false, 6 >::tryDequeueUntilMC().

523  {
524  Segment* next = s->nextSegment();
525  if (!next) {
526  DCHECK_GE(t, s->minTicket() + SegmentSize);
527  auto diff = t - (s->minTicket() + SegmentSize);
528  if (diff > 0) {
529  auto dur = std::chrono::microseconds(diff);
530  auto deadline = std::chrono::steady_clock::now() + dur;
531  WaitOptions opt;
532  opt.spin_max(dur);
534  deadline, opt, [s] { return s->nextSegment(); });
535  next = s->nextSegment();
536  if (next) {
537  return next;
538  }
539  }
540  next = allocNextSegment(s);
541  }
542  DCHECK(next);
543  return next;
544  }
Segment * allocNextSegment(Segment *s)
std::chrono::steady_clock::time_point now()
static constexpr size_t SegmentSize
uint64_t diff(uint64_t a, uint64_t b)
Definition: FutexTest.cpp:135
static set< string > s
spin_result spin_pause_until(std::chrono::time_point< Clock, Duration > const &deadline, WaitOptions const &opt, F f)
Definition: Spin.h:36
def next(obj)
Definition: ast.py:58
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE Segment* folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::head ( ) const
inlineprivatenoexcept

Definition at line 675 of file UnboundedQueue.h.

675  {
676  return c_.head.load(std::memory_order_acquire);
677  }
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE size_t folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::index ( Ticket  t) const
inlineprivatenoexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE Ticket folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::producerTicket ( ) const
inlineprivatenoexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::reclaimRemainingSegments ( )
inlineprivate

reclaimRemainingSegments

Definition at line 651 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::~UnboundedQueue().

651  {
652  auto h = head();
653  auto s = h->nextSegment();
654  h->setNextSegment(nullptr);
655  reclaimSegment(h);
656  while (s) {
657  auto next = s->nextSegment();
658  delete s;
659  s = next;
660  }
661  }
*than *hazptr_holder h
Definition: Hazptr.h:116
void reclaimSegment(Segment *s) noexcept
FOLLY_ALWAYS_INLINE Segment * head() const noexcept
static set< string > s
def next(obj)
Definition: ast.py:58
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::reclaimSegment ( Segment s)
inlineprivatenoexcept

reclaimSegment

Definition at line 627 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::advanceHead(), folly::UnboundedQueue< T, false, 6 >::advanceHeadToTicket(), and folly::UnboundedQueue< T, false, 6 >::reclaimRemainingSegments().

627  {
628  if (SPSC) {
629  delete s;
630  } else {
631  s->retire(); // defined in hazptr_obj_base_linked
632  }
633  }
static set< string > s
static constexpr bool SPSC
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::responsibleForAdvance ( Ticket  t) const
inlineprivatenoexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::responsibleForAlloc ( Ticket  t) const
inlineprivatenoexcept

Definition at line 667 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::enqueueCommon().

667  {
668  return (t & (SegmentSize - 1)) == 0;
669  }
static constexpr size_t SegmentSize
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::setConsumerTicket ( Ticket  t)
inlineprivatenoexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::setHead ( Segment s)
inlineprivatenoexcept

Definition at line 691 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::advanceHead(), and folly::UnboundedQueue< T, false, 6 >::advanceHeadToTicket().

691  {
692  DCHECK(SingleConsumer);
693  c_.head.store(s, std::memory_order_relaxed);
694  }
static set< string > s
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::setProducerTicket ( Ticket  t)
inlineprivatenoexcept

Definition at line 713 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::fetchIncrementProducerTicket().

713  {
714  p_.ticket.store(t, std::memory_order_release);
715  }
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
void folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::setTail ( Segment s)
inlineprivatenoexcept

Definition at line 696 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::advanceTail().

696  {
697  DCHECK(SPSC);
698  p_.tail.store(s, std::memory_order_release);
699  }
static set< string > s
static constexpr bool SPSC
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
size_t folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::size ( ) const
inlinenoexcept

size

Definition at line 340 of file UnboundedQueue.h.

340  {
341  auto p = producerTicket();
342  auto c = consumerTicket();
343  return p > c ? p - c : 0;
344  }
FOLLY_ALWAYS_INLINE Ticket consumerTicket() const noexcept
FOLLY_ALWAYS_INLINE Ticket producerTicket() const noexcept
char c
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE Segment* folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::tail ( ) const
inlineprivatenoexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::try_dequeue ( T item)
inlinenoexcept

try_dequeue

Definition at line 273 of file UnboundedQueue.h.

Referenced by enq_deq_test().

273  {
274  auto o = try_dequeue();
275  if (LIKELY(o.has_value())) {
276  item = std::move(*o);
277  return true;
278  }
279  return false;
280  }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define LIKELY(x)
Definition: Likely.h:47
FOLLY_ALWAYS_INLINE folly::Optional< T > try_dequeue() noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE folly::Optional<T> folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::try_dequeue ( )
inlinenoexcept

Definition at line 282 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::try_dequeue(), and folly::UnboundedQueue< T, false, 6 >::try_dequeue_for().

282  {
284  }
FOLLY_ALWAYS_INLINE folly::Optional< T > tryDequeueUntil(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
LogLevel min
Definition: LogLevel.cpp:30
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Rep , typename Period >
FOLLY_ALWAYS_INLINE bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::try_dequeue_for ( T item,
const std::chrono::duration< Rep, Period > &  duration 
)
inlinenoexcept

try_dequeue_for

Definition at line 309 of file UnboundedQueue.h.

Referenced by enq_deq_test(), and folly::UnboundedQueue< T, false, 6 >::try_dequeue_for().

311  {
312  folly::Optional<T> o = try_dequeue_for(duration);
313 
314  if (LIKELY(o.has_value())) {
315  item = std::move(*o);
316  return true;
317  }
318 
319  return false;
320  }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define LIKELY(x)
Definition: Likely.h:47
FOLLY_CPP14_CONSTEXPR bool has_value() const noexcept
Definition: Optional.h:296
FOLLY_ALWAYS_INLINE bool try_dequeue_for(T &item, const std::chrono::duration< Rep, Period > &duration) noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Rep , typename Period >
FOLLY_ALWAYS_INLINE folly::Optional<T> folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::try_dequeue_for ( const std::chrono::duration< Rep, Period > &  duration)
inlinenoexcept

Definition at line 323 of file UnboundedQueue.h.

324  {
326  if (LIKELY(o.has_value())) {
327  return o;
328  }
329  return tryDequeueUntil(std::chrono::steady_clock::now() + duration);
330  }
FOLLY_ALWAYS_INLINE folly::Optional< T > tryDequeueUntil(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
std::chrono::steady_clock::time_point now()
#define LIKELY(x)
Definition: Likely.h:47
FOLLY_CPP14_CONSTEXPR bool has_value() const noexcept
Definition: Optional.h:296
FOLLY_ALWAYS_INLINE folly::Optional< T > try_dequeue() noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::try_dequeue_until ( T item,
const std::chrono::time_point< Clock, Duration > &  deadline 
)
inlinenoexcept

try_dequeue_until

Definition at line 288 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::try_dequeue_until().

290  {
292 
293  if (LIKELY(o.has_value())) {
294  item = std::move(*o);
295  return true;
296  }
297 
298  return false;
299  }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define LIKELY(x)
Definition: Likely.h:47
FOLLY_CPP14_CONSTEXPR bool has_value() const noexcept
Definition: Optional.h:296
FOLLY_ALWAYS_INLINE bool try_dequeue_until(T &item, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE folly::Optional<T> folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::try_dequeue_until ( const std::chrono::time_point< Clock, Duration > &  deadline)
inlinenoexcept

Definition at line 302 of file UnboundedQueue.h.

303  {
304  return tryDequeueUntil(deadline);
305  }
FOLLY_ALWAYS_INLINE folly::Optional< T > tryDequeueUntil(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
FOLLY_ALWAYS_INLINE const T* folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::try_peek ( )
inlinenoexcept

try_peek

Definition at line 333 of file UnboundedQueue.h.

Referenced by enq_deq_test().

333  {
334  /* This function is supported only for USPSC and UMPSC queues. */
335  DCHECK(SingleConsumer);
337  }
LogLevel min
Definition: LogLevel.cpp:30
FOLLY_ALWAYS_INLINE const T * tryPeekUntil(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE folly::Optional<T> folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::tryDequeueUntil ( const std::chrono::time_point< Clock, Duration > &  deadline)
inlineprivatenoexcept

tryDequeueUntil

Definition at line 420 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::try_dequeue(), folly::UnboundedQueue< T, false, 6 >::try_dequeue_for(), and folly::UnboundedQueue< T, false, 6 >::try_dequeue_until().

421  {
422  if (SingleConsumer) {
423  Segment* s = head();
424  return tryDequeueUntilSC(s, deadline);
425  } else {
426  // Using hazptr_holder instead of hazptr_local because it is
427  // possible to call ~T() and it may happen to use hazard pointers.
428  hazptr_holder<Atom> hptr;
429  Segment* s = hptr.get_protected(c_.head);
430  return tryDequeueUntilMC(s, deadline);
431  }
432  }
FOLLY_ALWAYS_INLINE folly::Optional< T > tryDequeueUntilMC(Segment *s, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
FOLLY_ALWAYS_INLINE Segment * head() const noexcept
static set< string > s
FOLLY_ALWAYS_INLINE folly::Optional< T > tryDequeueUntilSC(Segment *s, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE folly::Optional<T> folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::tryDequeueUntilMC ( Segment s,
const std::chrono::time_point< Clock, Duration > &  deadline 
)
inlineprivatenoexcept

tryDequeueUntilMC

Definition at line 457 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::tryDequeueUntil().

459  {
460  while (true) {
461  Ticket t = consumerTicket();
462  if (UNLIKELY(t >= (s->minTicket() + SegmentSize))) {
463  s = getAllocNextSegment(s, t);
464  DCHECK(s);
465  continue;
466  }
467  size_t idx = index(t);
468  Entry& e = s->entry(idx);
469  if (UNLIKELY(!tryDequeueWaitElem(e, t, deadline))) {
470  return folly::Optional<T>();
471  }
472  if (!c_.ticket.compare_exchange_weak(
473  t, t + 1, std::memory_order_acq_rel, std::memory_order_acquire)) {
474  continue;
475  }
476  auto ret = e.takeItem();
477  if (responsibleForAdvance(t)) {
478  advanceHead(s);
479  }
480  return ret;
481  }
482  }
FOLLY_ALWAYS_INLINE bool responsibleForAdvance(Ticket t) const noexcept
Segment * getAllocNextSegment(Segment *s, Ticket t) noexcept
FOLLY_ALWAYS_INLINE bool tryDequeueWaitElem(Entry &e, Ticket t, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
FOLLY_ALWAYS_INLINE Ticket consumerTicket() const noexcept
static constexpr size_t SegmentSize
FOLLY_ALWAYS_INLINE size_t index(Ticket t) const noexcept
static set< string > s
void advanceHead(Segment *s) noexcept
#define UNLIKELY(x)
Definition: Likely.h:48
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE folly::Optional<T> folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::tryDequeueUntilSC ( Segment s,
const std::chrono::time_point< Clock, Duration > &  deadline 
)
inlineprivatenoexcept

tryDequeueUntilSC

Definition at line 436 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::tryDequeueUntil().

438  {
439  Ticket t = consumerTicket();
440  DCHECK_GE(t, s->minTicket());
441  DCHECK_LT(t, (s->minTicket() + SegmentSize));
442  size_t idx = index(t);
443  Entry& e = s->entry(idx);
444  if (UNLIKELY(!tryDequeueWaitElem(e, t, deadline))) {
445  return folly::Optional<T>();
446  }
447  setConsumerTicket(t + 1);
448  auto ret = e.takeItem();
449  if (responsibleForAdvance(t)) {
450  advanceHead(s);
451  }
452  return ret;
453  }
FOLLY_ALWAYS_INLINE bool responsibleForAdvance(Ticket t) const noexcept
FOLLY_ALWAYS_INLINE bool tryDequeueWaitElem(Entry &e, Ticket t, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
FOLLY_ALWAYS_INLINE Ticket consumerTicket() const noexcept
static constexpr size_t SegmentSize
FOLLY_ALWAYS_INLINE void setConsumerTicket(Ticket t) noexcept
FOLLY_ALWAYS_INLINE size_t index(Ticket t) const noexcept
static set< string > s
void advanceHead(Segment *s) noexcept
#define UNLIKELY(x)
Definition: Likely.h:48
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::tryDequeueWaitElem ( Entry e,
Ticket  t,
const std::chrono::time_point< Clock, Duration > &  deadline 
)
inlineprivatenoexcept

tryDequeueWaitElem

Definition at line 486 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::tryDequeueUntilMC(), folly::UnboundedQueue< T, false, 6 >::tryDequeueUntilSC(), and folly::UnboundedQueue< T, false, 6 >::tryPeekUntil().

489  {
490  if (LIKELY(e.tryWaitUntil(deadline))) {
491  return true;
492  }
493  return t < producerTicket();
494  }
#define LIKELY(x)
Definition: Likely.h:47
FOLLY_ALWAYS_INLINE Ticket producerTicket() const noexcept
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
template<typename Clock , typename Duration >
FOLLY_ALWAYS_INLINE const T* folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::tryPeekUntil ( const std::chrono::time_point< Clock, Duration > &  deadline)
inlineprivatenoexcept

tryPeekUntil

Definition at line 498 of file UnboundedQueue.h.

Referenced by folly::UnboundedQueue< T, false, 6 >::try_peek().

499  {
500  Segment* s = head();
501  Ticket t = consumerTicket();
502  DCHECK_GE(t, s->minTicket());
503  DCHECK_LT(t, (s->minTicket() + SegmentSize));
504  size_t idx = index(t);
505  Entry& e = s->entry(idx);
506  if (UNLIKELY(!tryDequeueWaitElem(e, t, deadline))) {
507  return nullptr;
508  }
509  return e.peekItem();
510  }
FOLLY_ALWAYS_INLINE bool tryDequeueWaitElem(Entry &e, Ticket t, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
FOLLY_ALWAYS_INLINE Ticket consumerTicket() const noexcept
static constexpr size_t SegmentSize
FOLLY_ALWAYS_INLINE size_t index(Ticket t) const noexcept
FOLLY_ALWAYS_INLINE Segment * head() const noexcept
static set< string > s
#define UNLIKELY(x)
Definition: Likely.h:48

Member Data Documentation

template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
constexpr size_t folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::Align = 1u << LgAlign
staticprivate

Definition at line 224 of file UnboundedQueue.h.

template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
Consumer folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::c_
private
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
Producer folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::p_
private
template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
constexpr bool folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::SPSC = SingleProducer && SingleConsumer
staticprivate

Definition at line 221 of file UnboundedQueue.h.

template<typename T, bool SingleProducer, bool SingleConsumer, bool MayBlock, size_t LgSegmentSize = 8, size_t LgAlign = constexpr_log2(hardware_destructive_interference_size), template< typename > class Atom = std::atomic>
constexpr size_t folly::UnboundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, Atom >::Stride = SPSC || (LgSegmentSize <= 1) ? 1 : 27
staticprivate

Definition at line 222 of file UnboundedQueue.h.


The documentation for this class was generated from the following file: