public class RingBufferControl extends RingBufferConsumerControl
This code is substantially based on the ingenious work done by Martin Thompson on what he calls "Mechanical Sympathy." It leans heavily on the source code from version 3.0.0.beta2 of the LMAX-exchange Disruptor but has been completely refactored in order to invert separate the control mechanism from what is being controlled and to simplify the API.
For more information on the LMAX Disruptor, see:
http://lmax-exchange.github.com/disruptor/
Employ Martin Thompson's "mechanical sympathy" to the concurrency control mechanism for a ring buffer. It directly borrows from their code base and as of the time this class was written, it has about 20-30% more throughput than their own ring buffer as measured by their own OneToOne benchmark test and about 15x faster as measured on their ThreeToOne test (on my machine, 64bit Linux, 64bit Java 6 Jvm).
This class is incredibly temperamental and must strictly be used the way it was intended. Misuse can easily lead to lockups, missed sequences, etc.
In general, the RingBufferControl
is the logic that controls the entries in a ring buffer, but not the ring buffer itself. These classes
make no assumptions about where the data is stored (other than in physical memory), or what type it is.
The RingBufferControl
is completely analogous to a traditional "condition variable." Just like a Condition Variable is the synchronization
mechanism that gates concurrent access to some 'condition', but says nothing about what the 'condition' actually is, the RingBufferControl
gates concurrent access to the publishing and consuming of data in a ring buffer.
The 'consumer side' control and the 'publishing side' control are broken into two separate classes. This class represents control of the publish
side of the ring buffer however, it inherits from the RingBufferConsumerControl
which represents the consumer side.
These two base primitives can only be used with one consuming thread and one publishing thread, however, they form the building blocks for several
other configurations (see RingBufferControlMulticaster
and RingBufferControlMultiplexor
)
RingBufferConsumerControl.ConsumerWaitStrategy
ACQUIRE_STOP_REQUEST, bufferSize, indexMask, INITIAL_CURSOR_VALUE, iter, p1, p2, p3, p4, p5, p6, publishCursor, spin, stop, stopIsCommon, tail, UNAVAILABLE, waitStrategy, yield
Constructor and Description |
---|
RingBufferControl(int sizePowerOfTwo)
Creates a
RingBufferControl with a RingBufferConsumerControl.yield consumer
wait strategy. |
RingBufferControl(int sizePowerOfTwo,
RingBufferConsumerControl.ConsumerWaitStrategy waitStrategy)
Creates a
RingBufferControl with the given wait strategy. |
Modifier and Type | Method and Description |
---|---|
long |
claim(int requestedNumberOfSlots)
This is used by the publishing thread to claim the given number of entries
in the buffer.
|
protected void |
clear() |
void |
publish(long sequence)
Once the publisher has readied the buffer entries that were claimed, this method
allows the consumer to be notified that they are ready.
|
long |
publishStop()
The
RingBufferControl can ONLY be stopped from the publish side. |
availableTo, availableTo, consumeAsIterable, consumeAsIterator, doNotifyProcessed, getTail, index, isShutdown, notifyProcessed, sumPaddingToPreventOptimisation, tryAvailableTo, tryAvailableTo
public RingBufferControl(int sizePowerOfTwo) throws IllegalArgumentException
RingBufferControl
with a RingBufferConsumerControl.yield
consumer
wait strategy.sizePowerOfTwo
- is the size of the buffer being controlled. It must be a
power of 2.IllegalArgumentException
- if the sizePowerOfTwo isn't a power of 2.public RingBufferControl(int sizePowerOfTwo, RingBufferConsumerControl.ConsumerWaitStrategy waitStrategy) throws IllegalArgumentException
RingBufferControl
with the given wait strategy.sizePowerOfTwo
- is the size of the buffer being controlled. It must be a
power of 2.waitStrategy
- is the implementation of RingBufferConsumerControl.waitStrategy
to use.IllegalArgumentException
- if the sizePowerOfTwo isn't a power of 2.public long claim(int requestedNumberOfSlots)
requestedNumberOfSlots
- is the number of entries in the buffer we need
to wait for to be open.publish(long)
or the RingBufferConsumerControl.index(long)
methods.public void publish(long sequence)
sequence
- is the sequence returned from the claim(int)
call.public long publishStop()
The RingBufferControl
can ONLY be stopped from the publish side. The publisher needs to call publishStop to stop the consumer. Once the
consumer reaches this point in the sequence, the consumer will receive a RingBufferConsumerControl.ACQUIRE_STOP_REQUEST
returned from either
RingBufferConsumerControl.availableTo()
or RingBufferConsumerControl.tryAvailableTo()
.
Once that happens the RingBufferConsumerControl.isShutdown()
will return true
on both the publisher and consumer sides.
protected void clear()
clear
in class RingBufferConsumerControl
Copyright © 2018. All rights reserved.