How can I use coroutines along withTimeout while h...
# coroutines
s
How can I use coroutines along withTimeout while having the non-coroutine external I/O operation to execute? for example I have a simple code here which work with cancellations by timeout only if I have a delay() function, but as soon as I mock it with thread.sleep() - it stops working. what's wrong with this code implementation? -
Copy code
fun main() {
  val list = listOf("1", "2", "3", "4", "5") //listOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" )
  val threadPool = Executors.newFixedThreadPool(3)!!
  //val threadPoolAsCouritineDispatcher = threadPool.asCoroutineDispatcher()

  fun <A> Iterable<A>.parallelIterWithExecutorAttempt(
      exec: ExecutorService,
      block: (A) -> Unit) {
    this.asIterable().map { exec.submit { block(it) } }.forEach { it.get() }
  }

 suspend fun work(item: String) =
     withContext(Dispatchers.Default) {

       //<https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt>
       //<https://medium.com/@elizarov/blocking-threads-suspending-coroutines-d33e11bf4761>

       val result = withTimeoutOrNull(timeMillis = 130L) {
          repeat(10) { i ->
            println("ListItem=$item -> I'm sleeping on iteration -> $i ...")
            delay(50L)
            //Thread.sleep(50L) //to mimic non-couroutine external I/O operaion
          }
          println("process=$item ->Done") // will get cancelled before it produces this result
        }
    }

  println("parallelIterWithExecutor")
  runBlocking {
    list.parallelIterWithExecutorAttempt(threadPool) { item ->
      launch {
        work(item)
      } //timeout...
    }
  }
  println("end of life for process") 
}
l
Non cancellable code is not cancellable because cancellation is cooperative.
s
Ok. so how to achieve what I need then?
l
@Serge Either find a cancellable way to do what you want, or if it's okay for you, leak the blocking operation on cancellation, hoping it doesn't continue for too long and doesn't overlap too much with other work, by using suspendCancellableCoroutine + a way to run the blocking code on another thread (e.g. using
GlobalScope.launch(<http://Dispatchers.IO|Dispatchers.IO>)  { … }
) before attempting to resume the continuation.