Blocking chanel.send until received data are processed

I have Channel<>(Channel.RENDEZVOUS)
It has no buffer, so it automatically blocks send until receive is used.

Is there any way how to block even longer?
I need to do that until the data are processed

I’m now doing this ugly hack

Producer:

do {
     ... prepare data ...
     channel.send(event)
     // block until data are processed by consumer
     eventProcessingLock.withLock { log("Processing event done") }
} while()

Consumer:

try {
    do {
        delay(10)
    } while (channel.isEmpty)
    eventProcessingLock.lock()
    val data = channel.receive()
    ... process data ...
} finally {
   eventProcessingLock.unlock()
}

where eventProcessingLock is just Mutex

Is there something less ugly?

You can not use a Channel at all. You could simply pass a callback, that gives you exactly that behaviour for free.
The only difference, really is that that would be executing on the same coroutine, wether that’s an issue it depends on your use-case.

I’m actually converting callback call to channel.
I’m getting some Events objects from non Kotlin callback API

And I want to write business logic like this using corountines:

send("hallo")
if (waitOnData() == "ready") {
   send("asking question")
   val reply = waitOnData()
   if (reply ....) {
       sendData(...)
       waitOnData()
   }
} else {
   ...
}

The only issue is that this callback API sadly recycle Events object after callback is finished. So I need to lock callback function until data is processed.

So I rewrote val reply = waitOnData() to

val result = waitOnData {
   ... process data ...
}

And keep lock in callback until process data block is done.
But I need to keep the lock as short as possible.
Otherwise I will not get new data.

So If I cannot lock producer before I call receive() because I then never get a new data, because producer will be locked forever. So in the moment when Channel is empty I need just wait for new data, but not keep lock open.

But yes. I can probably stop using Chanel and do all work just by storing events to the local field and do everything just with the right locking.