Skip to content

Commit

Permalink
Deprecate SendChannel.isFull and ReceiveChannel.isEmpty properties
Browse files Browse the repository at this point in the history
  • Loading branch information
ndkoval authored and elizarov committed Mar 20, 2019
1 parent ac136d6 commit b6f5b2c
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 30 deletions.
12 changes: 7 additions & 5 deletions kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
// ------ 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
Expand Down Expand Up @@ -402,7 +403,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
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 {
Expand Down Expand Up @@ -561,7 +562,8 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
// ------ 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 {
Expand Down Expand Up @@ -748,7 +750,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
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 {
Expand Down Expand Up @@ -782,7 +784,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
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 {
Expand Down
23 changes: 12 additions & 11 deletions kotlinx-coroutines-core/common/src/channels/Channel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ public interface SendChannel<in E> {
* 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.
Expand Down Expand Up @@ -151,13 +152,14 @@ public interface ReceiveChannel<out E> {
* 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.
Expand Down Expand Up @@ -188,7 +190,7 @@ public interface ReceiveChannel<out E> {
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_.
*
Expand Down Expand Up @@ -227,7 +229,7 @@ public interface ReceiveChannel<out E> {
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_.
*/
Expand Down Expand Up @@ -273,9 +275,8 @@ public interface ReceiveChannel<out E> {
*/
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
Expand All @@ -297,7 +298,7 @@ public interface ChannelIterator<out E> {

/**
* 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_.
*
Expand Down
14 changes: 5 additions & 9 deletions kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ class ArrayChannelTest : TestBase() {
@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)
Expand All @@ -25,29 +23,27 @@ class ArrayChannelTest : TestBase() {
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)
}
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)
}
Expand All @@ -56,9 +52,9 @@ class ArrayChannelTest : TestBase() {
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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class RendezvousChannelTest : TestBase() {
@Test
fun testSimple() = runTest {
val q = Channel<Int>(Channel.RENDEZVOUS)
check(q.isEmpty && q.isFull)
expect(1)
val sender = launch {
expect(4)
Expand All @@ -31,14 +30,13 @@ class RendezvousChannelTest : TestBase() {
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)
Expand All @@ -51,9 +49,9 @@ class RendezvousChannelTest : TestBase() {
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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ private class ChannelViaBroadcast<E>(
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()
Expand Down

0 comments on commit b6f5b2c

Please sign in to comment.