Package com.bytedesk.core.uid.buffer
Class RingBuffer
java.lang.Object
com.bytedesk.core.uid.buffer.RingBuffer
Represents a ring buffer based on array.<br>
Using array could improve read element performance due to the CUP cache line. To prevent
the side effect of False Sharing, slots:</b> each element of the array is a slot, which is be set with a UID
flags:</b> flag array corresponding the same index with the slots, indicates whether can take or put slot
tail:</b> a sequence of the max slot position to produce
cursor:</b> a sequence of the min slot position to consume
PaddedAtomicLong
is using on 'tail' and 'cursor'<p>
A ring buffer is consisted of:
- Author:
- yutianbao
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate BufferPaddingExecutor
Executor of padding bufferprivate final int
The size of RingBuffer's slots, each slot hold a UIDprivate static final long
private static final long
private final AtomicLong
Cursor: current position sequence to consumestatic final int
private final PaddedAtomicLong[]
private final long
private static final org.slf4j.Logger
private final int
Threshold for trigger padding bufferprivate RejectedPutBufferHandler
Reject put/take buffer handle policyprivate RejectedTakeBufferHandler
private final long[]
private static final int
Constantsprivate final AtomicLong
Tail: last position sequence to produce -
Constructor Summary
ConstructorsConstructorDescriptionRingBuffer
(int bufferSize) Constructor with buffer size, paddingFactor default as 50RingBuffer
(int bufferSize, int paddingFactor) Constructor with buffer size and padding factor -
Method Summary
Modifier and TypeMethodDescriptionprotected int
calSlotIndex
(long sequence) Calculate slot index with the slot sequence (sequence % bufferSize)protected void
discardPutBuffer
(RingBuffer ringBuffer, long uid) Discard policy forRejectedPutBufferHandler
, we just do loggingprotected void
exceptionRejectedTakeBuffer
(RingBuffer ringBuffer) Policy forRejectedTakeBufferHandler
, throwsRuntimeException
after loggingint
long
long
getTail()
Gettersprivate PaddedAtomicLong[]
initFlags
(int bufferSize) Initialize flags as CAN_PUT_FLAGboolean
put
(long uid) Put an UID in the ring and tail moved<br> We use 'synchronized' to guarantee the UID fill in slot and publish new tail sequence as atomic operations<br> Note that: </b> It is recommended to put UID in a serialize way, cause we once batch generate a series UIDs and put the one by one into the buffer, so it is unnecessary put in multi-threadsvoid
setBufferPaddingExecutor
(BufferPaddingExecutor bufferPaddingExecutor) Settersvoid
setRejectedPutHandler
(RejectedPutBufferHandler rejectedPutHandler) void
setRejectedTakeHandler
(RejectedTakeBufferHandler rejectedTakeHandler) long
take()
Take an UID of the ring at the next cursor, this is a lock free operation by using atomic cursor<p> Before getting the UID, we also check whether reach the padding threshold, the padding buffer operation will be triggered in another thread<br> If there is no more available UID to be taken, the specifiedRejectedTakeBufferHandler
will be applied<br>toString()
-
Field Details
-
LOGGER
private static final org.slf4j.Logger LOGGER -
START_POINT
private static final int START_POINTConstants- See Also:
-
CAN_PUT_FLAG
private static final long CAN_PUT_FLAG- See Also:
-
CAN_TAKE_FLAG
private static final long CAN_TAKE_FLAG- See Also:
-
DEFAULT_PADDING_PERCENT
public static final int DEFAULT_PADDING_PERCENT- See Also:
-
bufferSize
private final int bufferSizeThe size of RingBuffer's slots, each slot hold a UID -
indexMask
private final long indexMask -
slots
private final long[] slots -
flags
-
tail
Tail: last position sequence to produce -
cursor
Cursor: current position sequence to consume -
paddingThreshold
private final int paddingThresholdThreshold for trigger padding buffer -
rejectedPutHandler
Reject put/take buffer handle policy -
rejectedTakeHandler
-
bufferPaddingExecutor
Executor of padding buffer
-
-
Constructor Details
-
RingBuffer
public RingBuffer(int bufferSize) Constructor with buffer size, paddingFactor default as 50- Parameters:
bufferSize
- must be positive & a power of 2
-
RingBuffer
public RingBuffer(int bufferSize, int paddingFactor) Constructor with buffer size and padding factor- Parameters:
bufferSize
- must be positive and a power of 2paddingFactor
- percent in (0, 100), padding buffer when tail-cursor < threshold
-
-
Method Details
-
put
public boolean put(long uid) Put an UID in the ring and tail moved<br> We use 'synchronized' to guarantee the UID fill in slot and publish new tail sequence as atomic operations<br> Note that: </b> It is recommended to put UID in a serialize way, cause we once batch generate a series UIDs and put the one by one into the buffer, so it is unnecessary put in multi-threads- Parameters:
uid
-- Returns:
- false means that the buffer is full, apply
RejectedPutBufferHandler
-
take
public long take()Take an UID of the ring at the next cursor, this is a lock free operation by using atomic cursor<p> Before getting the UID, we also check whether reach the padding threshold, the padding buffer operation will be triggered in another thread<br> If there is no more available UID to be taken, the specifiedRejectedTakeBufferHandler
will be applied<br>- Returns:
- UID
- Throws:
IllegalStateException
- if the cursor moved back
-
calSlotIndex
protected int calSlotIndex(long sequence) Calculate slot index with the slot sequence (sequence % bufferSize) -
discardPutBuffer
Discard policy forRejectedPutBufferHandler
, we just do logging -
exceptionRejectedTakeBuffer
Policy forRejectedTakeBufferHandler
, throwsRuntimeException
after logging -
initFlags
Initialize flags as CAN_PUT_FLAG -
getTail
public long getTail()Getters -
getCursor
public long getCursor() -
getBufferSize
public int getBufferSize() -
setBufferPaddingExecutor
Setters -
setRejectedPutHandler
-
setRejectedTakeHandler
-
toString
-