https://kotlinlang.org logo
Title
j

Joris PZ

10/13/2018, 7:13 PM
Hi all, I am playing around with actors and channels, and I am wondering about the best way to structure my code. I have an actor that needs to read messages from two incoming sources, and as usual it needs to process messages one at a time so it can safely update internal state without further synchronization. I have wrapped my actor in a class, and expose a
.run()
method to start its internal loop:
class MyActor {

  suspend fun run() {
    while(true) {
      select<Unit> {
        one.onReceive { ... }
        two.onReceive { ... }
      }
    }
  } 

}
Now, I am wondering about two things. First, where do I define the necessary channels? Do I do it in some configuration code and inject them as properties through a constructor, like so:
class MyActor(private val one: ReceiveChannel<Query>, private val two: ReceiveChannel<Command>)
Or do I define them in the actor itself, and expose them for outside clients to use?
class MyActor {
  private val _one = Channel<Query>()

  val one: SendChannel<Query>
    get() = _one
}
My second question is related - is it a good idea (or even idiomatic) to use Channels to define the API to my actor? Or is it better/more common to offer message functions hiding the channels for the client, like
suspend fun query(query: Query) {
    one.send(query)
  }
Thanks for any feedback!
g

gildor

10/14/2018, 4:03 AM
Just as side note that can be useful for you, check this PR to kotlinx.coroutines that introduces concept of type safe actors: https://github.com/Kotlin/kotlinx.coroutines/pull/485
j

Joris PZ

10/14/2018, 6:08 AM
Oh this is very relevant, I will study the implementation. Thanks!