From be39731f493018706aa0ae190f8dc1b863c31e25 Mon Sep 17 00:00:00 2001 From: Maria Sokolova Date: Fri, 9 Feb 2024 20:43:14 +0100 Subject: [PATCH 1/3] Calling a function containing atomic operations from a different file results in the failure of Native incremental compilation. Made BufferedChannel#sendImpl function private. This is a WA for KT-65554 --- .../common/src/channels/BufferedChannel.kt | 25 +++++++++++++++++-- .../src/channels/ConflatedBufferedChannel.kt | 21 ---------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt index 9224ae8fce..a0281ef966 100644 --- a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt @@ -241,7 +241,7 @@ internal open class BufferedChannel( /** * Abstract send implementation. */ - protected inline fun sendImpl( + private inline fun sendImpl( /* The element to be sent. */ element: E, /* The waiter to be stored in case of suspension, @@ -350,6 +350,27 @@ internal open class BufferedChannel( } } + protected fun trySendDropOldest(element: E): ChannelResult = + sendImpl( // <-- this is an inline function + element = element, + // Put the element into the logical buffer even + // if this channel is already full, the `onSuspend` + // callback below extract the first (oldest) element. + waiter = BUFFERED, + // Finish successfully when a rendezvous has happened + // or the element has been buffered. + onRendezvousOrBuffered = { return success(Unit) }, + // In case the algorithm decided to suspend, the element + // was added to the buffer. However, as the buffer is now + // overflowed, the first (oldest) element has to be extracted. + onSuspend = { segm, i -> + dropFirstElementUntilTheSpecifiedCellIsInTheBuffer(segm.id * SEGMENT_SIZE + i) + return success(Unit) + }, + // If the channel is closed, return the corresponding result. + onClosed = { return closed(sendException) } + ) + private inline fun sendImplOnNoWaiter( /* The working cell is specified by the segment and the index in it. */ @@ -1587,7 +1608,7 @@ internal open class BufferedChannel( * It is nulled-out on both completion and cancellation paths that * could happen concurrently. */ - @BenignDataRace + //@BenignDataRace private var continuation: CancellableContinuationImpl? = null // `hasNext()` is just a special receive operation. diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt index a2d3a10322..5c7f151022 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt @@ -72,27 +72,6 @@ internal open class ConflatedBufferedChannel( return success(Unit) } - private fun trySendDropOldest(element: E): ChannelResult = - sendImpl( // <-- this is an inline function - element = element, - // Put the element into the logical buffer even - // if this channel is already full, the `onSuspend` - // callback below extract the first (oldest) element. - waiter = BUFFERED, - // Finish successfully when a rendezvous has happened - // or the element has been buffered. - onRendezvousOrBuffered = { return success(Unit) }, - // In case the algorithm decided to suspend, the element - // was added to the buffer. However, as the buffer is now - // overflowed, the first (oldest) element has to be extracted. - onSuspend = { segm, i -> - dropFirstElementUntilTheSpecifiedCellIsInTheBuffer(segm.id * SEGMENT_SIZE + i) - return success(Unit) - }, - // If the channel is closed, return the corresponding result. - onClosed = { return closed(sendException) } - ) - @Suppress("UNCHECKED_CAST") override fun registerSelectForSend(select: SelectInstance<*>, element: Any?) { // The plain `send(..)` operation never suspends. Thus, either this From 3f60c28bef5090123a7c8a2c75a6020a7fcd2577 Mon Sep 17 00:00:00 2001 From: Maria Sokolova Date: Wed, 14 Feb 2024 11:00:43 +0100 Subject: [PATCH 2/3] fixup --- kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt index a0281ef966..000b87987d 100644 --- a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt @@ -1608,7 +1608,7 @@ internal open class BufferedChannel( * It is nulled-out on both completion and cancellation paths that * could happen concurrently. */ - //@BenignDataRace + @BenignDataRace private var continuation: CancellableContinuationImpl? = null // `hasNext()` is just a special receive operation. From f29bb49d8b506bcdf19a1739eb0e4a110a31da78 Mon Sep 17 00:00:00 2001 From: Maria Sokolova Date: Sun, 10 Mar 2024 22:09:47 +0100 Subject: [PATCH 3/3] Dropped a comment --- kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt index 000b87987d..fb6846ef4e 100644 --- a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt @@ -350,6 +350,8 @@ internal open class BufferedChannel( } } + // Note: this function is temporarily moved from ConflatedBufferedChannel to BufferedChannel class, because of this issue: KT-65554. + // For now, an inline function, which invokes atomic operations, may only be called within a parent class. protected fun trySendDropOldest(element: E): ChannelResult = sendImpl( // <-- this is an inline function element = element,