From 0cf99bcd265371b2e4a6bb6be6fb4cb56092d89b Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 5 Jun 2018 19:03:44 +0300 Subject: [PATCH] Explain why non-constant placeholder is required --- .../experimental/internal/LockFreeMPSCQueue.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeMPSCQueue.kt b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeMPSCQueue.kt index d878812daf..61cfcfdb69 100644 --- a/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeMPSCQueue.kt +++ b/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeMPSCQueue.kt @@ -123,8 +123,17 @@ internal class LockFreeMPSCQueueCore(private val capacity: Int) { private fun fillPlaceholder(index: Int, element: E): Core? { val old = array.get(index and mask) + /* + * addLast actions: + * 1) Commit tail slot + * 2) Write element to array slot + * 3) Check for array copy + * + * If copy happened between 2 and 3 then the consumer might have consumed our element, + * then another producer might have written its placeholder in our slot, so we should + * perform *unique* check that current placeholder is our to avoid overwriting another producer placeholder + */ if (old is Placeholder && old.index == index) { - // that is OUR placeholder and only we can fill it in array.set(index and mask, element) // we've corrected missing element, should check if that propagated to further copies, just in case return this