Max
Max

Reputation: 5081

Asynchronously constructing a producer

I have a case where I want to construct a ReceiveChannel using produce, asynchronously, but it's hanging. Here's a simplified example:

runBlocking {
    val deferredChannel = async {
        produce<String> { send("foo") }
    }

    val channel = deferredChannel.await()

    println("Got channel")

    val value = channel.receive()

    println("Got value $value")
}

Neither println is hit. It's plausible that there's some kind of coroutine deadlock going on, but I'm not not clear where/how.

How can I produce a ReceiveChannel asynchronously?

Edit: It works if I change produce to produce(capacity = 1), but why is that? Shouldn't the await() succeed, at least, regardless of the producer's capacity? And what if I want to keep capacity=0?

Upvotes: 2

Views: 78

Answers (1)

DarkCygnus
DarkCygnus

Reputation: 7838

It works if I change produce to produce(capacity = 1), but why is that? Shouldn't the await() succeed, at least, regardless of the producer's capacity?

Checking the docs on the produce() method you call, and specifically the docs on the capacity parameter and Channel we have (emphasis mine):

When capacity is 0 – it creates RendezvousChannel. This channel does not have any buffer at all. An element is transferred from sender to receiver only when send and receive invocations meet in time (rendezvous), so send suspends until another coroutine invokes receive and receive suspends until another coroutine invokes send.

This could be the reason why it's hanging. You are calling send on your async thread and then await for it... however, as the docs say, no other co-routine has invoked receive yet... so it will suspend until that happens and in this case it hangs.

Checking that same link on Channel, we also see why giving it a number greater than 0 solves this (emphasis mine):

When capacity is positive, but less than UNLIMITED – it creates array-based channel with given capacity. This channel has an array buffer of a fixed capacity. Sender suspends only when buffer is full and receiver suspends only when buffer is empty.

Upvotes: 1

Related Questions