Mario Galic
Mario Galic

Reputation: 48400

Changing ExecutionContext of a Future after initialisation

I understand "ExecutionContext is like a cockroach":

We can’t talk about Futures without talking about its ExecutionContext: they form a duo (unfortunately)... It means the ExecutionContext was decided early on (generally on startup) and therefore is fixed. But callers should be able to decide on which ExecutionContext they want to run your function (like using their own). It’s not the responsibility of the callee service to enforce it (exceptions aside).

and we have to pass it in at construction time as implicit argument

object Future {
  def apply[T](body: =>T)(implicit executor: ExecutionContext)
}

and if we want to have full control in which thread pool the task executes we should use libraries like cats-effect.

Nevertheless, I was wondering is there any way at all we could hack a lazy initialised Future to make it run on a different execution context from the one it was initialised with? Perhaps some hideous reflective black magic, where we somehow identify the task and steal it from the queue it was put in?

For example, say we have a function which accepts a pass-by-name Future

def foo(f: => Future) = {
  val differentExecutionContext = ExecutionContext.fromExecutor(...
  /* run f on differentExecutionContext */
}

foo(Future(42)(ExecutionContext.Implicits.global))

Now what we could do is at call site use different execution context like so

val differentExecutionContext = ExecutionContext.fromExecutor(...
foo(Future(42)(differentExecutionContext))

however, this forces the user to remember to provide and use a different execution context. Is there any way Future(42) could run on differentExecutionContext inside foo instead of global, transparently to the user?

In case this is an XY problem, here is context.

Upvotes: 1

Views: 442

Answers (1)

simpadjo
simpadjo

Reputation: 4017

Don't think it's possible. => Future[T] is indistinguishable from just Future[T] when it comes to hacking. I imagine you'd like to do something like that:

f.asInstanceOf[SomeImplOfFuture[T]].setExecutionContext(myContexty).

But any such action would trigger execution of f.

Upvotes: 1

Related Questions