You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
mpmc xadd's poll uses the consumer index to move forward the consumers, but consumers that need to recognize that a rotation is in progress have to check consumerBuffer::index value.
The rotation in progress case can be handled more transpanrently by stealing the parity bit of consumerIndex, saving to read the consumerBuffer (and its index) field if not necessary.
The text was updated successfully, but these errors were encountered:
franz1981
changed the title
Mpmc xadd q poll can just use consumerIndex
Mpmc xadd q poll can use consumerIndex parity bit to mark a rotation
Oct 28, 2019
The changes of #281 have shown the need to simplify the mpmc xadd poll.
To summarize the findings for the future:
before the changes of #281, with chunkSize = 1 and 1 recycled chunk, a poll can trigger a mid-element rotation if the consumer read consumerChunk and consumerIndex right after the rotating consumer has won a casConsumerIndex, but hasn't yet soConsumerChunk the next one.
The mid-element consumer can see the old consumerChunk, now recycled for the next offer, matching ciChunkIndex and then making it able to perform a consume on it.
eg
C1: ci = 2 cc = 1
C1: start rotation: ci = 2 -> 3 and pool cc (cc->next!=null && cc->next = 2)
C2: read ci ( == 3), cc (==1)
P1: read a chunk (== 1) from the pool, soIndex(3) and writing the element & sequence on it
C2: check cc.index == ci ( == 3), sequence and consume it ie ci = 3->4
C1: end rotation: set cc = 1 -> 2
C3: cc = 2 and ci = 4: it BLOCKS
The issue happen because a rotation can change ci to point to a new chunk (!= next) and this chunk could be a pooled one right after winning the casConsumerIndex on rotation: with chunkSize > 1 (eg 2) the rotation can change ci, but it's forced to stay on the next chunk.
The only case that can make the mid-element to be consumed is with ciChunkIndex == ccChunkIndex and ci already rotated (ie pointing to the second element of next, yet not cc), but given that we need next to continue and cc could be either the current one (recycled too) or next, it will wait it to become next to proceed, avoid an early consume to happen.
The fix on the PR is valid for the chunkSize = 1 case, because it forces the distance of 1 between cc and ci when we handle the first element in the next chunk.
mpmc xadd's poll uses the consumer index to move forward the consumers, but consumers that need to recognize that a rotation is in progress have to check consumerBuffer::index value.
The rotation in progress case can be handled more transpanrently by stealing the parity bit of consumerIndex, saving to read the
consumerBuffer
(and its index) field if not necessary.The text was updated successfully, but these errors were encountered: