Deprecate `SendChannel.isFull` and `ReceiveChannel.isEmpty` properties
Fixes #1053
diff --git a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt
index 0835243..38f7c3b 100644
--- a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt
@@ -167,7 +167,8 @@
// ------ SendChannel ------
public final override val isClosedForSend: Boolean get() = closedForSend != null
- public final override val isFull: Boolean get() = queue.nextNode !is ReceiveOrClosed<*> && isBufferFull
+ public final override val isFull: Boolean get() = full
+ private val full: Boolean get() = queue.nextNode !is ReceiveOrClosed<*> && isBufferFull // TODO rename to `isFull`
public final override suspend fun send(element: E) {
// fast path -- try offer non-blocking
@@ -402,7 +403,7 @@
private fun <R> registerSelectSend(select: SelectInstance<R>, element: E, block: suspend (SendChannel<E>) -> R) {
while (true) {
if (select.isSelected) return
- if (isFull) {
+ if (full) {
val enqueueOp = TryEnqueueSendDesc(element, select, block)
val enqueueResult = select.performAtomicIfNotSelected(enqueueOp) ?: return
when {
@@ -561,7 +562,8 @@
// ------ ReceiveChannel ------
public final override val isClosedForReceive: Boolean get() = closedForReceive != null && isBufferEmpty
- public final override val isEmpty: Boolean get() = queue.nextNode !is Send && isBufferEmpty
+ public final override val isEmpty: Boolean get() = empty
+ private val empty: Boolean get() = queue.nextNode !is Send && isBufferEmpty // TODO rename to `isEmpty`
@Suppress("UNCHECKED_CAST")
public final override suspend fun receive(): E {
@@ -748,7 +750,7 @@
private fun <R> registerSelectReceive(select: SelectInstance<R>, block: suspend (E) -> R) {
while (true) {
if (select.isSelected) return
- if (isEmpty) {
+ if (empty) {
val enqueueOp = TryEnqueueReceiveDesc(select, block as (suspend (E?) -> R), nullOnClose = false)
val enqueueResult = select.performAtomicIfNotSelected(enqueueOp) ?: return
when {
@@ -782,7 +784,7 @@
private fun <R> registerSelectReceiveOrNull(select: SelectInstance<R>, block: suspend (E?) -> R) {
while (true) {
if (select.isSelected) return
- if (isEmpty) {
+ if (empty) {
val enqueueOp = TryEnqueueReceiveDesc(select, block, nullOnClose = true)
val enqueueResult = select.performAtomicIfNotSelected(enqueueOp) ?: return
when {
diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt
index 351bd49..286196d 100644
--- a/kotlinx-coroutines-core/common/src/channels/Channel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt
@@ -30,14 +30,15 @@
* Returns `true` if the channel is full (out of capacity) and the [send] attempt will suspend.
* This function returns `false` for [isClosedForSend] channel.
*
- * **Note: This is an experimental api.** This property may change its semantics and/or name in the future.
+ * @suppress **Will be removed in next releases, no replacement.**
*/
@ExperimentalCoroutinesApi
+ @Deprecated(level = DeprecationLevel.ERROR, message = "Will be removed in next releases without replacement")
public val isFull: Boolean
/**
- * Adds [element] into to this channel, suspending the caller while this channel [isFull],
- * or throws exception if the channel [isClosedForSend] (see [close] for details).
+ * Adds [element] into to this channel, suspending the caller while the buffer of this channel is full
+ * or if it does not exist, or throws exception if the channel [isClosedForSend] (see [close] for details).
*
* Note, that closing a channel _after_ this function had suspended does not cause this suspended send invocation
* to abort, because closing a channel is conceptually like sending a special "close token" over this channel.
@@ -151,13 +152,14 @@
* Returns `true` if the channel is empty (contains no elements) and the [receive] attempt will suspend.
* This function returns `false` for [isClosedForReceive] channel.
*
- * **Note: This is an experimental api.** This property may change its semantics and/or name in the future.
+ * @suppress **Will be removed in next releases, no replacement.**
*/
@ExperimentalCoroutinesApi
+ @Deprecated(level = DeprecationLevel.ERROR, message = "Will be removed in next releases without replacement")
public val isEmpty: Boolean
/**
- * Retrieves and removes the element from this channel suspending the caller while this channel [isEmpty]
+ * Retrieves and removes the element from this channel suspending the caller while this channel is empty,
* or throws [ClosedReceiveChannelException] if the channel [isClosedForReceive].
* If the channel was closed because of the exception, it is called a _failed_ channel and this function
* throws the original [close][SendChannel.close] cause exception.
@@ -188,7 +190,7 @@
public val onReceive: SelectClause1<E>
/**
- * Retrieves and removes the element from this channel suspending the caller while this channel [isEmpty]
+ * Retrieves and removes the element from this channel suspending the caller while this channel is empty,
* or returns `null` if the channel is [closed][isClosedForReceive] without cause
* or throws the original [close][SendChannel.close] cause exception if the channel has _failed_.
*
@@ -227,7 +229,7 @@
public val onReceiveOrNull: SelectClause1<E?>
/**
- * Retrieves and removes the element from this channel, or returns `null` if this channel [isEmpty]
+ * Retrieves and removes the element from this channel, or returns `null` if this channel is empty
* or is [isClosedForReceive] without cause.
* It throws the original [close][SendChannel.close] cause exception if the channel has _failed_.
*/
@@ -273,9 +275,8 @@
*/
public interface ChannelIterator<out E> {
/**
- * Returns `true` if the channel has more elements suspending the caller while this channel
- * [isEmpty][ReceiveChannel.isEmpty] or returns `false` if the channel
- * [isClosedForReceive][ReceiveChannel.isClosedForReceive] without cause.
+ * Returns `true` if the channel has more elements, suspending the caller while this channel is empty,
+ * or returns `false` if the channel [isClosedForReceive][ReceiveChannel.isClosedForReceive] without cause.
* It throws the original [close][SendChannel.close] cause exception if the channel has _failed_.
*
* This function retrieves and removes the element from this channel for the subsequent invocation
@@ -297,7 +298,7 @@
/**
* Retrieves and removes the element from this channel suspending the caller while this channel
- * [isEmpty][ReceiveChannel.isEmpty] or throws [ClosedReceiveChannelException] if the channel
+ * is empty or throws [ClosedReceiveChannelException] if the channel
* [isClosedForReceive][ReceiveChannel.isClosedForReceive] without cause.
* It throws the original [close][SendChannel.close] cause exception if the channel has _failed_.
*
diff --git a/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt
index 56a1c5a..308f8f3 100644
--- a/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt
@@ -11,12 +11,10 @@
@Test
fun testSimple() = runTest {
val q = Channel<Int>(1)
- check(q.isEmpty && !q.isFull)
expect(1)
val sender = launch {
expect(4)
q.send(1) // success -- buffered
- check(!q.isEmpty && q.isFull)
expect(5)
q.send(2) // suspends (buffer full)
expect(9)
@@ -25,7 +23,6 @@
val receiver = launch {
expect(6)
check(q.receive() == 1) // does not suspend -- took from buffer
- check(!q.isEmpty && q.isFull) // waiting sender's element moved to buffer
expect(7)
check(q.receive() == 2) // does not suspend (takes from sender)
expect(8)
@@ -33,21 +30,20 @@
expect(3)
sender.join()
receiver.join()
- check(q.isEmpty && !q.isFull)
finish(10)
}
@Test
fun testClosedBufferedReceiveOrNull() = runTest {
val q = Channel<Int>(1)
- check(q.isEmpty && !q.isFull && !q.isClosedForSend && !q.isClosedForReceive)
+ check(!q.isClosedForSend && !q.isClosedForReceive)
expect(1)
launch {
expect(5)
- check(!q.isEmpty && !q.isFull && q.isClosedForSend && !q.isClosedForReceive)
+ check(q.isClosedForSend && !q.isClosedForReceive)
assertEquals(42, q.receiveOrNull())
expect(6)
- check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive)
+ check(q.isClosedForSend && q.isClosedForReceive)
assertEquals(null, q.receiveOrNull())
expect(7)
}
@@ -56,9 +52,9 @@
expect(3)
q.close() // goes on
expect(4)
- check(!q.isEmpty && !q.isFull && q.isClosedForSend && !q.isClosedForReceive)
+ check(q.isClosedForSend && !q.isClosedForReceive)
yield()
- check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive)
+ check(q.isClosedForSend && q.isClosedForReceive)
finish(8)
}
diff --git a/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt
index 60bccef..fafda0d 100644
--- a/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt
+++ b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt
@@ -11,7 +11,6 @@
@Test
fun testSimple() = runTest {
val q = Channel<Int>(Channel.RENDEZVOUS)
- check(q.isEmpty && q.isFull)
expect(1)
val sender = launch {
expect(4)
@@ -31,14 +30,13 @@
expect(3)
sender.join()
receiver.join()
- check(q.isEmpty && q.isFull)
finish(10)
}
@Test
fun testClosedReceiveOrNull() = runTest {
val q = Channel<Int>(Channel.RENDEZVOUS)
- check(q.isEmpty && q.isFull && !q.isClosedForSend && !q.isClosedForReceive)
+ check(!q.isClosedForSend && !q.isClosedForReceive)
expect(1)
launch {
expect(3)
@@ -51,9 +49,9 @@
q.send(42)
expect(5)
q.close()
- check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive)
+ check(q.isClosedForSend && q.isClosedForReceive)
yield()
- check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive)
+ check(q.isClosedForSend && q.isClosedForReceive)
finish(7)
}
diff --git a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt
index 465699e..6e1ee2b 100644
--- a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt
+++ b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt
@@ -54,6 +54,7 @@
val sub = broadcast.openSubscription()
override val isClosedForReceive: Boolean get() = sub.isClosedForReceive
+ @Suppress("DEPRECATION_ERROR")
override val isEmpty: Boolean get() = sub.isEmpty
override suspend fun receive(): E = sub.receive()