Ensure that inline functions only access atomics from the same class (#4041)
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
diff --git a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt
index 9224ae8..fb6846e 100644
--- a/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt
@@ -241,7 +241,7 @@
/**
* Abstract send implementation.
*/
- protected inline fun <R> sendImpl(
+ private inline fun <R> sendImpl(
/* The element to be sent. */
element: E,
/* The waiter to be stored in case of suspension,
@@ -350,6 +350,29 @@
}
}
+ // 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<Unit> =
+ 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. */
diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt
index a2d3a10..5c7f151 100644
--- a/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt
@@ -72,27 +72,6 @@
return success(Unit)
}
- private fun trySendDropOldest(element: E): ChannelResult<Unit> =
- 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