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 BufferPaddingExecutorExecutor of padding bufferprivate final intThe size of RingBuffer's slots, each slot hold a UIDprivate static final longprivate static final longprivate final AtomicLongCursor: current position sequence to consumestatic final intprivate final PaddedAtomicLong[]private final longprivate static final org.slf4j.Loggerprivate final intThreshold for trigger padding bufferprivate RejectedPutBufferHandlerReject put/take buffer handle policyprivate RejectedTakeBufferHandlerprivate final long[]private static final intConstantsprivate final AtomicLongTail: 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 intcalSlotIndex(long sequence) Calculate slot index with the slot sequence (sequence % bufferSize)protected voiddiscardPutBuffer(RingBuffer ringBuffer, long uid) Discard policy forRejectedPutBufferHandler, we just do loggingprotected voidexceptionRejectedTakeBuffer(RingBuffer ringBuffer) Policy forRejectedTakeBufferHandler, throwsRuntimeExceptionafter loggingintlonglonggetTail()Gettersprivate PaddedAtomicLong[]initFlags(int bufferSize) Initialize flags as CAN_PUT_FLAGbooleanput(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-threadsvoidsetBufferPaddingExecutor(BufferPaddingExecutor bufferPaddingExecutor) SettersvoidsetRejectedPutHandler(RejectedPutBufferHandler rejectedPutHandler) voidsetRejectedTakeHandler(RejectedTakeBufferHandler rejectedTakeHandler) longtake()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 specifiedRejectedTakeBufferHandlerwill 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 specifiedRejectedTakeBufferHandlerwill 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, throwsRuntimeExceptionafter 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
-