https://kotlinlang.org logo
#coroutines
Title
# coroutines
a

ansman

02/24/2019, 4:14 PM
What’s more idiomatic:
Copy code
fun events(channel: SendChannel<Event>)
fun events(scope: CoroutineScope): ReceiveChannel<Event>
In my case I need to add a listener when calling
events
and remove it when the channel is closed
a

ansman

02/24/2019, 4:18 PM
I don’t have multiple consumers and I need the caller to be the one to close the channel
a

ansman

02/24/2019, 4:18 PM
Oh, I’ll try that.
d

Dominaezzz

02/24/2019, 4:20 PM
But to answer your actual question, I think the second one is more idiomatic. 🙂
a

ansman

02/24/2019, 4:21 PM
Hmm, I don’t really think BroadcastChannel would fit my use case because I need a clear open and close event
d

Dominaezzz

02/24/2019, 4:22 PM
Makes sense.
Even
fun CoroutineScope.events(): ReceiveChannel<Event>
is more idiomatic if you're a spawning a coroutine in the function.
a

ansman

02/24/2019, 4:25 PM
It’s really strange though, my producer is closed instantly and I can’t figure out why:
Copy code
override fun events(scope: CoroutineScope): ReceiveChannel<Unit> =
        scope.produce(capacity = Channel.CONFLATED) {
            val listener = { offer(Unit) }
            addListener(listener)
            invokeOnClose { removeListener(listener) }
        }
d

Dominaezzz

02/24/2019, 4:27 PM
Oh, I don't think you need the
produce
.
Just create a channel and return it.
a

ansman

02/24/2019, 4:28 PM
The reason why I need it is because it will be closed when the scope’s job is cancelled
If I have a channel I need to close it manually
d

Dominaezzz

02/24/2019, 4:32 PM
Hmm, there's a way to register a callback with the scope's context to handle closing but I don't know how atm.
You definitely don't need a coroutine for this.
a

ansman

02/24/2019, 4:34 PM
Well I don’t want the caller to have to worry about closing the channel
d

Dico

02/24/2019, 4:45 PM
This is a common problem indeed, where the channel is closed when the
produce
coroutine completes, when that is not the intention. Here is a potential workaround:
Copy code
produce {
    // your stuff, done with procuding ...
    suspendCoroutineCancellable<Unit> { cont ->
        channel.invokeOnClose { cont.resume(Unit) }
    }   
}
a

ansman

02/24/2019, 4:46 PM
Oh right, of course. The coroutine completes. What would be the best way to have this behavior then?
d

Dico

02/24/2019, 4:47 PM
well, there are 2 options for you, the one above or to manually close the channel when the scope is cancelled.
I'm actually confused now, as channels should only be closed for sending when the producer completes. Any sent items should still be receivable.
Ah, it's because of the listener thing you're doing.
a

ansman

02/24/2019, 4:53 PM
Yeah, I’m trying to bridge a callback API
d

Dico

02/24/2019, 4:53 PM
I see
3 Views