@@ -122,7 +122,10 @@ internal class LockFreeMPSCQueueCore<E : Any>(private val capacity: Int) {
122122 }
123123
124124 private fun fillPlaceholder (index : Int , element : E ): Core <E >? {
125- if (array.compareAndSet(index and mask, PLACEHOLDER , element)) {
125+ val old = array.get(index and mask)
126+ if (old is Placeholder && old.index == index) {
127+ // that is OUR placeholder and only we can fill it in
128+ array.set(index and mask, element)
126129 // we've corrected missing element, should check if that propagated to further copies, just in case
127130 return this
128131 }
@@ -137,15 +140,10 @@ internal class LockFreeMPSCQueueCore<E : Any>(private val capacity: Int) {
137140 if (state and FROZEN_MASK != 0L ) return REMOVE_FROZEN // frozen -- cannot modify
138141 state.withState { head, tail ->
139142 if ((tail and mask) == (head and mask)) return null // empty
140- // because queue is Single Consumer, then element == null|PLACEHOLDER can only be when add has not finished yet
143+ // because queue is Single Consumer, then element == null|Placeholder can only be when add has not finished yet
141144 val element = array[head and mask] ? : return null
142- if (element == = PLACEHOLDER ) return null // same story -- consider it not added yet
143- check(element != = REMOVED ) { " This queue can have only one consumer" }
144- // tentatively remove element to let GC work
145- // we cannot put null into array, because copying thread could replace it with PLACEHOLDER
146- // and that is a disaster, so a separate REMOVED token is used here.
147- // Note: at most one REMOVED in the array, because single consumer.
148- array[head and mask] = REMOVED
145+ if (element is Placeholder ) return null // same story -- consider it not added yet
146+ // we cannot put null into array here, because copying thread could replace it with Placeholder and that is a disaster
149147 val newHead = (head + 1 ) and MAX_CAPACITY_MASK
150148 if (_state .compareAndSet(state, state.updateHead(newHead))) {
151149 array[head and mask] = null // now can safely put null (state was updated)
@@ -165,10 +163,8 @@ internal class LockFreeMPSCQueueCore<E : Any>(private val capacity: Int) {
165163 state.withState { head, _ ->
166164 check(head == oldHead) { " This queue can have only one consumer" }
167165 if (state and FROZEN_MASK != 0L ) {
168- // state was already frozen, so either old or REMOVED item could have been copied to next
169- val next = next()
170- next.array[head and next.mask] = REMOVED // make sure it is removed in new array regardless
171- return next // continue to correct head in next
166+ // state was already frozen, so removed element was copied to next
167+ return next() // continue to correct head in next
172168 }
173169 if (_state .compareAndSet(state, state.updateHead(newHead))) {
174170 array[head and mask] = null // now can safely put null (state was updated)
@@ -199,14 +195,19 @@ internal class LockFreeMPSCQueueCore<E : Any>(private val capacity: Int) {
199195 var index = head
200196 while (index and mask != tail and mask) {
201197 // replace nulls with placeholders on copy
202- next.array[index and next.mask] = array[index and mask] ? : PLACEHOLDER
198+ next.array[index and next.mask] = array[index and mask] ? : Placeholder (index)
203199 index++
204200 }
205201 next._state .value = state wo FROZEN_MASK
206202 }
207203 return next
208204 }
209205
206+ // Instance of this class is placed into array when we have to copy array, but addLast is in progress --
207+ // it had already reserved a slot in the array (with null) and have not yet put its value there.
208+ // Placeholder keeps the actual index (not masked) to distinguish placeholders on different wraparounds of array
209+ private class Placeholder (@JvmField val index : Int )
210+
210211 @Suppress(" PrivatePropertyName" )
211212 internal companion object {
212213 internal const val INITIAL_CAPACITY = 8
@@ -229,9 +230,6 @@ internal class LockFreeMPSCQueueCore<E : Any>(private val capacity: Int) {
229230 internal const val ADD_FROZEN = 1
230231 internal const val ADD_CLOSED = 2
231232
232- private val PLACEHOLDER = Symbol (" PLACEHOLDER" )
233- private val REMOVED = Symbol (" PLACEHOLDER" )
234-
235233 private infix fun Long.wo (other : Long ) = this and other.inv ()
236234 private fun Long.updateHead (newHead : Int ) = (this wo HEAD_MASK ) or (newHead.toLong() shl HEAD_SHIFT )
237235 private fun Long.updateTail (newTail : Int ) = (this wo TAIL_MASK ) or (newTail.toLong() shl TAIL_SHIFT )
0 commit comments