Put an UID in the ring & tail moved We use 'synchronized' to guarantee the UID fill in slot & 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,
(long uid)
| 109 | * @return false means that the buffer is full, apply {@link RejectedPutBufferHandler} |
| 110 | */ |
| 111 | public synchronized boolean put(long uid) { |
| 112 | long currentTail = tail.get(); |
| 113 | long currentCursor = cursor.get(); |
| 114 | |
| 115 | // tail catches the cursor, means that you can't put any cause of RingBuffer is full |
| 116 | long distance = currentTail - (currentCursor == START_POINT ? 0 : currentCursor); |
| 117 | if (distance == bufferSize - 1) { |
| 118 | rejectedPutHandler.rejectPutBuffer(this, uid); |
| 119 | return false; |
| 120 | } |
| 121 | |
| 122 | // 1. pre-check whether the flag is CAN_PUT_FLAG |
| 123 | int nextTailIndex = calSlotIndex(currentTail + 1); |
| 124 | if (flags[nextTailIndex].get() != CAN_PUT_FLAG) { |
| 125 | rejectedPutHandler.rejectPutBuffer(this, uid); |
| 126 | return false; |
| 127 | } |
| 128 | |
| 129 | // 2. put UID in the next slot |
| 130 | // 3. update next slot' flag to CAN_TAKE_FLAG |
| 131 | // 4. publish tail with sequence increase by one |
| 132 | slots[nextTailIndex] = uid; |
| 133 | flags[nextTailIndex].set(CAN_TAKE_FLAG); |
| 134 | tail.incrementAndGet(); |
| 135 | |
| 136 | // The atomicity of operations above, guarantees by 'synchronized'. In another word, |
| 137 | // the take operation can't consume the UID we just put, until the tail is published(tail.incrementAndGet()) |
| 138 | return true; |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Take an UID of the ring at the next cursor, this is a lock free operation by using atomic cursor<p> |
no test coverage detected