Q:

Kotlin actors goes to dead lock when capacity is less than number of messages

I wanted to benchmark akka actors with kotlin actors. With some very basic understanding of kotlin, I tried simple test with ping pong and program got stuck. It only progressed to completion only when I made capacity size same as number of messages. With my understanding both actors should continue doing its work and should not depend on capacity.
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.runBlocking

sealed class Message
class Ping(val replyTo: SendChannel<Message>) : Message()
object Pong : Message()

object Start : Message()

fun CoroutineScope.PingActor() = actor<Message>(capacity = 10) {
    for (msg in channel) { 
        when (msg) {
            is Ping ->
                msg.replyTo.send(Pong)
        }
    }
}

fun CoroutineScope.PongActor(pinger: SendChannel<Message>, count: Int, done: CompletableDeferred<Unit>) =
    actor<Message> (capacity = 10){
        var counter = count 

        for (msg in channel) { 
            when (msg) {
                is Start ->
                    for (i in 1..count) {
                        pinger.send(Ping(this.channel))
                    }

                is Pong -> {
                    counter -= 1
                    if (counter == 0) {
                        done.complete(Unit)
                    }
                }
            }

        }
    }

fun main() = runBlocking<Unit> {

    val response = CompletableDeferred<Unit>()
    val pinger = PingActor() 
    val ponger = PongActor(pinger, 100, response) 
    val startTime = System.nanoTime()

    ponger.send(Start)
    response.await()

    println("total time taken is ${System.nanoTime() - startTime}")
    pinger.close() 
    ponger.close()
}

A:

It only progressed to completion only when I made capacity size same as number of messages.

You can check that 50 capacity (for both actors) is actually enough. Let's see what happens with 10:

pinger receives the Start message, 
pinger tries to send 100 messages to ponger. 10 are sent, 11th blocks until there's more space in the queue. 
ponger handles the messages and sends 10 replies.
pinger can now send 10 more messages.
ponger tries to handle the 11th Ping, but blocks when sending the reply, because there are 10 messages in pinger's mailbox.

Note that pinger doesn't get to ever handling replies because it's still handling the Start message. 

