How to suspend kotlin coroutine until notified

Channels can be used for this (though they are more general):

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.

So create

val channel = Channel<Unit>(0)

And use channel.receive() for object.wait(), and channel.offer(Unit) for object.notify() (or send if you want to wait until the other coroutine receives).

For notifyAll, you can use BroadcastChannel instead.

You can of course easily encapsulate it:

inline class Waiter(private val channel: Channel<Unit> = Channel<Unit>(0)) {

    suspend fun doWait() { channel.receive() }
    fun doNotify() { channel.offer(Unit) }
}

It is possible to use the basic suspendCoroutine{..} function for that, e.g.

class SuspendWait() {
  private lateinit var myCont: Continuation<Unit>
  suspend fun sleepAndWait() = suspendCoroutine<Unit>{ cont ->
    myCont = cont
  }

  fun resume() {
    val cont = myCont
    myCont = null
    cont.resume(Unit)
  }
}

It is clear, the code have issues, e.g. myCont field is not synchonized, it is expected that sleepAndWait is called before the resume and so on, hope the idea is clear now.

There is another solution with the Mutex class from the kotlinx.coroutines library.

class SuspendWait2 {
  private val mutex = Mutex(locaked = true)
  suspend fun sleepAndWait() = mutex.withLock{}
  fun resume() {
    mutex.unlock()
  }
}