Class ConcurrentBlockingRingBuffer<T>
java.lang.Object
org.jgroups.util.ConcurrentBlockingRingBuffer<T>
- Type Parameters:
T- T
- All Implemented Interfaces:
Iterable<T>, Collection<T>, BlockingQueue<T>, Queue<T>
MPSC queue, based on a ring buffer implementation which optionally blocks on adding or removing of elements.
The main fields are read-index (ri), write-index (wi) and size (all AtomicIntegers). Producers change wi and size, the single consumer changes ri and size.
A producer tries to increment size. If unsuccessful, it drops the message (or blocks). If successful, it increments wi and writes the element to array[wi]. If size was incremented from 0 -> 1, a producer also wakes up the consumer.
The single consumer tries to remove size elements (drainTo() or poll()), but returns when a null element is found (see below). It then decrements size by the number of removed elements (N for drainTo() and 1 for a successful poll()). If no elements are in the ring buffer, the consumer blocks (if configured), until it is woken up by a producer adding the first element to the empty queue.
Note that this class is designed for a single consumer and has undefined behavior if multiple consumers are used.
There is a special case that has the consumer busy-polling (ri=wi=1): assume we have producers P1-P3, each adding an element concurrently. P3 successfully incremented size from 0->1 and set wi=3. P2 also incremented size from 1->2 and set wi=1, but didn't yet write to the array. P3 incremented size from 2->3 and set wi=2, but also didn't write to the array yet. P1 woke up the consumer, but the consumer saw array[1]=null, array[2]=null, array[3]=el3 (written by P3). The consumer therefore returns on the first element because it is null, but continues looping because size=3. Only when P1 and P2 write their respective elements will the consumer be able to make progress.
The main fields are read-index (ri), write-index (wi) and size (all AtomicIntegers). Producers change wi and size, the single consumer changes ri and size.
A producer tries to increment size. If unsuccessful, it drops the message (or blocks). If successful, it increments wi and writes the element to array[wi]. If size was incremented from 0 -> 1, a producer also wakes up the consumer.
The single consumer tries to remove size elements (drainTo() or poll()), but returns when a null element is found (see below). It then decrements size by the number of removed elements (N for drainTo() and 1 for a successful poll()). If no elements are in the ring buffer, the consumer blocks (if configured), until it is woken up by a producer adding the first element to the empty queue.
Note that this class is designed for a single consumer and has undefined behavior if multiple consumers are used.
There is a special case that has the consumer busy-polling (ri=wi=1): assume we have producers P1-P3, each adding an element concurrently. P3 successfully incremented size from 0->1 and set wi=3. P2 also incremented size from 1->2 and set wi=1, but didn't yet write to the array. P3 incremented size from 2->3 and set wi=2, but also didn't write to the array yet. P1 woke up the consumer, but the consumer saw array[1]=null, array[2]=null, array[3]=el3 (written by P3). The consumer therefore returns on the first element because it is null, but continues looping because size=3. Only when P1 and P2 write their respective elements will the consumer be able to make progress.
- Since:
- 5.5.0
- Author:
- Bela Ban
-
Nested Class Summary
Nested Classes -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final AtomicReferenceArray<T> protected final booleanprotected final booleanprotected final intprotected static final IntUnaryOperatorprotected static final IntBinaryOperatorprotected final IntUnaryOperatorprotected final IntUnaryOperatorprotected final Lockprotected final Conditionprotected final Conditionprotected intprotected final AtomicIntegerprotected final AtomicInteger -
Constructor Summary
ConstructorsConstructorDescriptionConcurrentBlockingRingBuffer(int capacity) ConcurrentBlockingRingBuffer(int capacity, boolean block_on_empty, boolean block_on_full) -
Method Summary
Modifier and TypeMethodDescriptionbooleanbooleanaddAll(Collection<? extends T> c) protected intadvance(int idx) protected intadvance(int idx, int delta) intcapacity()voidclear()booleanbooleancontainsAll(Collection<?> c) contents()static <T> ConcurrentBlockingRingBuffer<T> createBlocking(int capacity) intdrainTo(Collection<? super T> c) intdrainTo(Collection<? super T> c, int max) element()booleanisEmpty()iterator()booleanbooleanpeek()poll()voidintintremove()booleanbooleanremoveAll(Collection<?> c) booleanbooleanretainAll(Collection<?> c) protected voidprotected voidintsize()take()Object[]toArray()<T1> T1[]toArray(T1[] a) toString()intMethods inherited from class Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface Collection
equals, hashCode, parallelStream, spliterator, stream, toArray
-
Field Details
-
capacity
protected final int capacity -
array
-
wi
-
ri
protected int ri -
size
-
block_on_empty
protected final boolean block_on_empty -
block_on_full
protected final boolean block_on_full -
lock
-
not_empty
-
not_full
-
INCR
-
INCR_INDEX
-
DECR
-
DECR_DELTA
-
-
Constructor Details
-
ConcurrentBlockingRingBuffer
public ConcurrentBlockingRingBuffer(int capacity) -
ConcurrentBlockingRingBuffer
public ConcurrentBlockingRingBuffer(int capacity, boolean block_on_empty, boolean block_on_full)
-
-
Method Details
-
createBlocking
-
capacity
public int capacity() -
readIndex
public int readIndex() -
writeIndex
public int writeIndex() -
put
- Specified by:
putin interfaceBlockingQueue<T>- Throws:
InterruptedException
-
add
- Specified by:
addin interfaceBlockingQueue<T>- Specified by:
addin interfaceCollection<T>- Specified by:
addin interfaceQueue<T>
-
addAll
- Specified by:
addAllin interfaceCollection<T>
-
offer
-
offer
- Specified by:
offerin interfaceBlockingQueue<T>- Throws:
InterruptedException
-
clear
public void clear()- Specified by:
clearin interfaceCollection<T>
-
isEmpty
public boolean isEmpty()- Specified by:
isEmptyin interfaceCollection<T>
-
poll
-
poll
- Specified by:
pollin interfaceBlockingQueue<T>- Throws:
InterruptedException
-
drainTo
- Specified by:
drainToin interfaceBlockingQueue<T>
-
drainTo
- Specified by:
drainToin interfaceBlockingQueue<T>
-
element
-
peek
-
take
- Specified by:
takein interfaceBlockingQueue<T>- Throws:
InterruptedException
-
remove
-
remove
- Specified by:
removein interfaceBlockingQueue<T>- Specified by:
removein interfaceCollection<T>
-
containsAll
- Specified by:
containsAllin interfaceCollection<T>
-
contains
- Specified by:
containsin interfaceBlockingQueue<T>- Specified by:
containsin interfaceCollection<T>
-
iterator
-
toArray
- Specified by:
toArrayin interfaceCollection<T>
-
toArray
public <T1> T1[] toArray(T1[] a) - Specified by:
toArrayin interfaceCollection<T>
-
removeAll
- Specified by:
removeAllin interfaceCollection<T>
-
removeIf
- Specified by:
removeIfin interfaceCollection<T>
-
retainAll
- Specified by:
retainAllin interfaceCollection<T>
-
size
public int size()- Specified by:
sizein interfaceCollection<T>
-
remainingCapacity
public int remainingCapacity()- Specified by:
remainingCapacityin interfaceBlockingQueue<T>
-
toString
-
contents
-
advance
protected int advance(int idx) -
advance
protected int advance(int idx, int delta) -
signalNotEmpty
protected void signalNotEmpty() -
signalNotFull
protected void signalNotFull()
-