Skip to content

Commit 29e8213

Browse files
authored
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
1 parent c990f59 commit 29e8213

File tree

2 files changed

+24
-22
lines changed

2 files changed

+24
-22
lines changed

kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt

+24-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ internal open class BufferedChannel<E>(
241241
/**
242242
* Abstract send implementation.
243243
*/
244-
protected inline fun <R> sendImpl(
244+
private inline fun <R> sendImpl(
245245
/* The element to be sent. */
246246
element: E,
247247
/* The waiter to be stored in case of suspension,
@@ -350,6 +350,29 @@ internal open class BufferedChannel<E>(
350350
}
351351
}
352352

353+
// Note: this function is temporarily moved from ConflatedBufferedChannel to BufferedChannel class, because of this issue: KT-65554.
354+
// For now, an inline function, which invokes atomic operations, may only be called within a parent class.
355+
protected fun trySendDropOldest(element: E): ChannelResult<Unit> =
356+
sendImpl( // <-- this is an inline function
357+
element = element,
358+
// Put the element into the logical buffer even
359+
// if this channel is already full, the `onSuspend`
360+
// callback below extract the first (oldest) element.
361+
waiter = BUFFERED,
362+
// Finish successfully when a rendezvous has happened
363+
// or the element has been buffered.
364+
onRendezvousOrBuffered = { return success(Unit) },
365+
// In case the algorithm decided to suspend, the element
366+
// was added to the buffer. However, as the buffer is now
367+
// overflowed, the first (oldest) element has to be extracted.
368+
onSuspend = { segm, i ->
369+
dropFirstElementUntilTheSpecifiedCellIsInTheBuffer(segm.id * SEGMENT_SIZE + i)
370+
return success(Unit)
371+
},
372+
// If the channel is closed, return the corresponding result.
373+
onClosed = { return closed(sendException) }
374+
)
375+
353376
private inline fun sendImplOnNoWaiter(
354377
/* The working cell is specified by
355378
the segment and the index in it. */

kotlinx-coroutines-core/common/src/channels/ConflatedBufferedChannel.kt

-21
Original file line numberDiff line numberDiff line change
@@ -72,27 +72,6 @@ internal open class ConflatedBufferedChannel<E>(
7272
return success(Unit)
7373
}
7474

75-
private fun trySendDropOldest(element: E): ChannelResult<Unit> =
76-
sendImpl( // <-- this is an inline function
77-
element = element,
78-
// Put the element into the logical buffer even
79-
// if this channel is already full, the `onSuspend`
80-
// callback below extract the first (oldest) element.
81-
waiter = BUFFERED,
82-
// Finish successfully when a rendezvous has happened
83-
// or the element has been buffered.
84-
onRendezvousOrBuffered = { return success(Unit) },
85-
// In case the algorithm decided to suspend, the element
86-
// was added to the buffer. However, as the buffer is now
87-
// overflowed, the first (oldest) element has to be extracted.
88-
onSuspend = { segm, i ->
89-
dropFirstElementUntilTheSpecifiedCellIsInTheBuffer(segm.id * SEGMENT_SIZE + i)
90-
return success(Unit)
91-
},
92-
// If the channel is closed, return the corresponding result.
93-
onClosed = { return closed(sendException) }
94-
)
95-
9675
@Suppress("UNCHECKED_CAST")
9776
override fun registerSelectForSend(select: SelectInstance<*>, element: Any?) {
9877
// The plain `send(..)` operation never suspends. Thus, either this

0 commit comments

Comments
 (0)