jonderry
jonderry

Reputation: 23633

How can I create an additional ExecutionContext that has similar properties to ExecutionContext.global?

In Scala, as far as I can tell, ExecutionContext.global is different from other ExecutionContext objects one might typically create using ExecutionContext.fromExecutor(...) because it can use scala.concurrent.blocking as a signal to spawn additional threads when an initially small thread pool becomes blocked with long-running, possibly io-bound computation. Is there a way to create another such ExecutionContext? Looking at the source code, it appears that ExecutionContext.global is created in a fairly unique way, through an internal call to impl.ExecutionContextImpl.fromExecutor(null: Executor), which is package-private.

Upvotes: 2

Views: 473

Answers (1)

Noah
Noah

Reputation: 13959

So you can create this pretty easily with this:

  scala.concurrent.ExecutionContext.fromExecutor(null)

It will go through the exact same process as ExecutionContext.global.

Behind the scenes this is just creating a ForkJoinPool with a special ThreadFactory for handling scala.concurrent.blocking signals. If you want more control you can just create your own ForkJoinPool and then provide a ThreadFactory doing something similar to what the scala version does(source) :

  class DefaultThreadFactory(daemonic: Boolean) extends ThreadFactory with ForkJoinPool.ForkJoinWorkerThreadFactory {
    def wire[T <: Thread](thread: T): T = {
      thread.setDaemon(daemonic)
      thread.setUncaughtExceptionHandler(uncaughtExceptionHandler)
      thread
    }

    def newThread(runnable: Runnable): Thread = wire(new Thread(runnable))

    def newThread(fjp: ForkJoinPool): ForkJoinWorkerThread = wire(new ForkJoinWorkerThread(fjp) with BlockContext {
      override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
        var result: T = null.asInstanceOf[T]
        ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker {
          @volatile var isdone = false
          override def block(): Boolean = {
            result = try thunk finally { isdone = true }
            true
          }
          override def isReleasable = isdone
        })
        result
      }
    })
  }

Additionally, Akka has an implimentation as well for its FJP.

Upvotes: 1

Related Questions