cds
2.3.2
|
Segmented queue. More...
#include <cds/intrusive/segmented_queue.h>
Public Types | |
typedef GC | gc |
Garbage collector. | |
typedef T | value_type |
type of the value stored in the queue | |
typedef Traits | traits |
Queue traits. | |
typedef traits::disposer | disposer |
value disposer, called only in clear() when the element to be dequeued | |
typedef traits::allocator | allocator |
Allocator maintaining the segments. | |
typedef traits::memory_model | memory_model |
Memory ordering. See cds::opt::memory_model option. | |
typedef traits::item_counter | item_counter |
Item counting policy, see cds::opt::item_counter option setter. | |
typedef traits::stat | stat |
Internal statistics policy. | |
typedef traits::lock_type | lock_type |
Type of mutex for maintaining an internal list of allocated segments. | |
typedef traits::permutation_generator | permutation_generator |
Random permutation generator for sequence [0, quasi-factor) | |
Public Member Functions | |
SegmentedQueue (size_t nQuasiFactor) | |
Initializes the empty queue. More... | |
~SegmentedQueue () | |
Clears the queue and deletes all internal data. | |
bool | enqueue (value_type &val) |
Inserts a new element at last segment of the queue. | |
value_type * | dequeue () |
Removes an element from first segment of the queue and returns it. More... | |
bool | push (value_type &val) |
Synonym for enqueue(value_type&) member function. | |
value_type * | pop () |
Synonym for dequeue() member function. | |
bool | empty () const |
Checks if the queue is empty. More... | |
void | clear () |
Clear the queue. More... | |
template<class Disposer > | |
void | clear_with (Disposer) |
Clear the queue. More... | |
size_t | size () const |
Returns queue's item count. | |
const stat & | statistics () const |
Returns reference to internal statistics. More... | |
size_t | quasi_factor () const |
Returns quasi factor, a power-of-two number. | |
Static Public Attributes | |
static const size_t | c_nHazardPtrCount = 2 |
Count of hazard pointer required for the algorithm. | |
Protected Attributes | |
segment_list | m_SegmentList |
List of segments. | |
item_counter | m_ItemCounter |
Item counter. | |
stat | m_Stat |
Internal statistics. | |
Segmented queue.
The queue is based on work
In this paper the authors offer a relaxed version of linearizability, so-called quasi-linearizability, that preserves some of the intuition, provides a flexible way to control the level of relaxation and supports th implementation of more concurrent and scalable data structure. Intuitively, the linearizability requires each run to be equivalent in some sense to a serial run of the algorithm. This equivalence to some serial run imposes strong synchronization requirements that in many cases results in limited scalability and synchronization bottleneck.
The general idea is that the queue maintains a linked list of segments, each segment is an array of nodes in the size of the quasi factor, and each node has a deleted boolean marker, which states if it has been dequeued. Each producer iterates over last segment in the linked list in some random permutation order. Whet it finds an empty cell it performs a CAS operation attempting to enqueue its new element. In case the entire segment has been scanned and no available cell is found (implying that the segment is full), then it attempts to add a new segment to the list.
The dequeue operation is similar: the consumer iterates over the first segment in the linked list in some random permutation order. When it finds an item which has not yet been dequeued, it performs CAS on its deleted marker in order to "delete" it, if succeeded this item is considered dequeued. In case the entire segment was scanned and all the nodes have already been dequeued (implying that the segment is empty), then it attempts to remove this segment from the linked list and starts the same process on the next segment. If there is no next segment, the queue is considered empty.
Based on the fact that most of the time threads do not add or remove segments, most of the work is done in parallel on different cells in the segments. This ensures a controlled contention depending on the segment size, which is quasi factor.
The segmented queue is an unfair queue since it violates the strong FIFO order but no more than quasi factor. This means that the consumer dequeues any item from the current first segment.
Template parameters:
GC
- a garbage collector, possible types are cds::gc::HP, cds::gc::DHPT
- the type of values stored in the queueTraits
- queue type traits, default is segmented_queue::traits
. segmented_queue::make_traits
metafunction can be used to construct the type traits.The queue stores the pointers to enqueued items so no special node hooks are needed.
|
inline |
Initializes the empty queue.
nQuasiFactor | Quasi factor. If it is not a power of 2 it is rounded up to nearest power of 2. Minimum is 2. |
|
inline |
Clear the queue.
The function repeatedly calls dequeue()
until it returns nullptr
. The disposer specified in Traits
template argument is called for each removed item.
|
inline |
Clear the queue.
The function repeatedly calls dequeue()
until it returns nullptr
. Disposer
is called for each removed item.
|
inline |
Removes an element from first segment of the queue and returns it.
If the queue is empty the function returns nullptr
.
The disposer specified in Traits
template argument is not called for returned item. You should manually dispose the item:
|
inline |
|
inline |
Returns reference to internal statistics.
The type of internal statistics is specified by Traits
template argument.