Package com.bytedesk.core.uid.buffer
Class RingBuffer
java.lang.Object
com.bytedesk.core.uid.buffer.RingBuffer
Represents a ring buffer based on array.
Using array could improve read element performance due to the CUP cache line. To prevent the side effect of False Sharing,slots: each element of the array is a slot, which is be set with a UID
flags: flag array corresponding the same index with the slots, indicates whether can take or put slot
tail: a sequence of the max slot position to produce
cursor: a sequence of the min slot position to consume
Using array could improve read element performance due to the CUP cache line. To prevent the side effect of False Sharing,
PaddedAtomicLong
is using on 'tail' and 'cursor'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
We use 'synchronized' to guarantee the UID fill in slot and publish new tail sequence as atomic operations
Note that: 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 cursortoString()
-
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
We use 'synchronized' to guarantee the UID fill in slot and publish new tail sequence as atomic operations
Note that: 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 cursorBefore getting the UID, we also check whether reach the padding threshold, the padding buffer operation will be triggered in another thread
If there is no more available UID to be taken, the specifiedRejectedTakeBufferHandler
will be applied- 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
-