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

uhe

03/17/2017, 2:26 PM
Copy code
val channel = Channel<Int>()
    launch(CommonPool) {
        delay(50)
        println("Closing and flushing channel")
        channel.closeAndFlush()
    }
    (0..3).map { number ->
        launch(context) {
            println("Sending $number")
            channel.send(number)
            println("$number sent")
        }
    }.forEach { it.join() }
    println("Done!")
which prints:
Copy code
Sending 0
Sending 1
Sending 2
Sending 3
Closing and flushing channel
0 sent
1 sent
2 sent
3 sent
Done!
e

elizarov

03/17/2017, 2:43 PM
That should work. Why would you need it, though?
u

uhe

03/17/2017, 3:07 PM
Well I'm trying to implement a component that takes jobs (not coroutine
Job
, but a custom domain job) and processes them in order (in the background). The result of the job should be sent back to the user. Like that:
Copy code
class ActorJobMessage(val job: BaseJob, val resultChannel: SendChannel<Result>)

    private fun createActor() {
        actor = actor(CommonPool) {
            for (message in this) {
                val result = message.job.process()
                message.resultChannel.sendSafely(result)
            }
        }
    }

    suspend private fun schedule(job: BaseJob): Result {
        val resultChannel = Channel<Result>()
        try {
            actor.sendOrNull(ActorJobMessage(job, resultChannel)) ?: return Error(701, "Cannot schedule jobs right now.")
            return resultChannel.receive()
        } finally {
            resultChannel.closeAndFlush()
        }
    }
If I don't flush the excess results the actor is blocked if
schedule
is cancelled before
result.receive
(
sendSafely
just ignores `ClosedSendChannelException`s)
k

kevinherron

03/17/2017, 3:11 PM
@uhe i have some similar constructs in some of my channel code...
not sure if it’s an indicator of something
u

uhe

03/17/2017, 3:13 PM
yeah, I'm still in the experimentation phase.. so I don't know if I'm just not using it correctly 😉
e

elizarov

03/17/2017, 3:25 PM
You should
cancel
an actor if you must terminate it without processing the rest of its inbox
close
is for “graceful” termination
u

uhe

03/17/2017, 3:27 PM
Yes, I have that as well. This
close
, however, affects the
SendChannel
that is created for each user.
if multiple users are scheduling jobs and one isn't interested in its result anymore, I don't want to cancel all other scheduled jobs
but you have a point, maybe I don't want to close gracefully at all... so this actor implementation might not be a fitting solution after all
2 Views