Search code examples
scalaconcurrencyparallel-processingexecutioncontext

Is an implicit execution context passed down to .par operations?


I have this situation:

  • method a: an implicit ec is created

  • method a: calls another method in a Future, i.e Future(anotherMethod). anotherMethod, and all its subsequent calls no longer have the ec from method a in scope.

Example code:

class Foo {
  private implicit val ec: ExecutionContextExecutor =
        ExecutionContext.fromExecutor(Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors()))

  private val anotherClass = new Bar()

  def methodA() = Future(anotherClass.anotherMethod())
}

I'm guessing, that any calls to .par, e.g someVector.par.map.().seq etc, from anotherMethod or any of its subsequent calls, will use the global execution context and not the custom one created in method a. Is my assumption correct?


Solution

  • I'm guessing, that any calls to .par, e.g someVector.par.map.().seq etc, from anotherMethod or any of its subsequent calls, will use the global execution context and not the custom one created in method a. Is my assumption correct?

    Let's split this answer in two. First, if you have any other methods in your call chain that will require an implicit ExecutionContext, they will get the one implicitly defined inside your top level methodA call.

    Otherwise, the parallel collection design in Scala has no notion of an ExecutionContext, that is strictly a property of Future. The parallel collection library has a notion of a TaskSupport which is responsible for scheduling inside the parallel collection:

    *  Parallel collections are modular in the way operations are scheduled. Each
    *  parallel collection is parameterized with a task support object which is
    *  responsible for scheduling and load-balancing tasks to processors.
    

    So these parallel collections will not have anything to do with the ExecutionContext declared in Foo. You can, however, explicitly set them via the tasksupport setter:

    val par = List(1,2,3,4).par
    par.tasksupport = new ForkJoinTaskSupport(new ForkJoinPool(4))