libDwm-0.9.45
Dwm::Thread::ConcurrentQueue< T > Class Template Reference

Concurrent queue template. More...

#include <DwmConcurrentQueue.hh>

Public Member Functions

 ConcurrentQueue (uint64_t maxLength=10000, useconds_t pushSleepUsecs=1000)
 Constructor.
 
 ~ConcurrentQueue ()
 Destructor. Walks the queue and deletes all entries.
 
bool PopFront (T &result)
 If the queue is not empty, pops the front entry into result and returns true.
 
bool PopFront (std::vector< T > &result)
 
bool PushBack (const T &t)
 Waits for the queue to not be full (see the Queue constructor), then pushes t onto the back of the queue and returns true.
 
bool PushBack (const std::vector< T > &t)
 

Detailed Description

template<typename T>
class Dwm::Thread::ConcurrentQueue< T >

Concurrent queue template.

This is based on an old article from Herb Sutter in Dr. Dobb's Journal, with modifications to support pushing and popping more than one entry at a time and reduction of the number of pointers.

The operations here are not wait-free, but I've tried to minimize contention. There is no contention between a producer (caller of PushBack()) and a consumer (caller of PopFront()). Short periods of contention will exist among producers. Short periods of contention will exist among consumers.

In my typical use, I only have one producer and one consumer per Queue. Occasionally I have the need for one producer and multiple consumers (for example, one producer feeding 'work' to multiple 'worker' threads). I rarely have a need for a single queue with multiple producers. If I need multiple producers, I almost always need (or want) multiple consumers. In those cases it almost always makes sense to have multiple queues, each with a single producer and a single consumer. For multiple wait-free producers, you've already thrown out the notion of ordered processing since you're not synchronizing the producers (else they'd be waiting for synchronization points). In most such cases, the solution with the most concurrency is multiple queues.

Of course there are exceptions. For example, you might want one producer to feed a set of consumers who then act as producers to feed one consumer (break a problem apart for multiple worker threads, then put it back together with a single consumer thread). But again, you've already thrown out strict ordering; that final consumer might as well be reading from multiple queues.

Constructor & Destructor Documentation

◆ ConcurrentQueue()

template<typename T >
Dwm::Thread::ConcurrentQueue< T >::ConcurrentQueue ( uint64_t maxLength = 10000,
useconds_t pushSleepUsecs = 1000 )
inline

Constructor.

maxLength is the maximum depth of the queue. When the queue reaches this depth, we will sleep pushSleepUsecs at a time until the queue is shallower than maxLength. This allows a consuming thread to catch up with PopFront().

Member Function Documentation

◆ PopFront()

template<typename T >
bool Dwm::Thread::ConcurrentQueue< T >::PopFront ( T & result)
inline

If the queue is not empty, pops the front entry into result and returns true.

If the queue is empty, returns false. A caller may choose to sleep a short period of time when false is returned.


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