Sergey Alaev
Sergey Alaev

Reputation: 3972

Is it possible to create own ExecutionContext that can properly handle scala.concurrent.blocking?

I'm writing close() method for my ScheduledExecutorService-based timer:

override def close(implicit executionContext: ExecutionContext): Future[Unit] = {
  val p = Promise[Unit]
  executionContext.execute(new Runnable() {
    override def run() = {
      blocking { 
        p complete Try {
          executor.shutdown()
          //OK for default global execution context
          //As we marked this code as blocking, additional thread
          //will be used on that so no threadpool starvation
          executor.awaitTermination(1, TimeUnit.DAYS)
        }
      }
    }
  })
  p.future
}

But if I implement ExecutionContext by myself, this code will block one of the pool's threads because I did not find any way to get that blocking context.

So, question: Is it possible to create own ExecutionContext that can properly handle scala.concurrent.blocking?

Upvotes: 2

Views: 273

Answers (1)

Michael Zajac
Michael Zajac

Reputation: 55569

Of course it's possible, it's just far from trivial. You would need to create an ExecutionContext that creates threads that mix in BlockContext which requires the following method:

def blockOn[T](thunk: => T)(implicit permission: CanAwait): T

blocking(thunk) will eventually lead to calling blockOn(thunk), and blockOn should figure out if the ExecutionContext has reached starvation and needs to do something or not. scala.concurrent.ExecutionContext.Implicits.global does it this way, but as you can see it uses a ForkJoinPool to do the heavy-lifting, and the implementation of that is thousands of lines of code.

Keep in mind that whether you use ExecutionContext.Implicits.global or your own `ExecutionContext, a thread will still be blocked by your code. The only difference is that the former spawns another thread to handle the fact that too many are blocked. Creating your own is likely to create some dangerous bugs though, as a lot of care has to be taken to avoid deadlocks or spawning too many threads.

Upvotes: 3

Related Questions