0

How can I run methods from inside a specific ExecutionContext only?

For example, consider this code:

trait SomeTrait {
  private var notThreadSafe = 0  // mutable var!
  def add(i: Int) = ???
  def subtract(i: Int) = ???
}

This code is only correct if methods add and subtract are called from the same thread only. What are the ways to make those methods always use a specific ExecutionContext (which would make sense if there is exactly 1 worker in the EC)? Any easy ways?

To get a grasp on the question, here are some example answers:

Answer1: wrap the body of all methods in Future.apply, like this:

class SomeClass {
  private implicit val ec: ExecutionContext = ???
  private var notThreadSafe = 0
  def add(i: Int) = Future {
    ???
  }
  def subtract(i: Int) = Future {
    ???
  }
}

Answer2: use an akka actor, convert all methods to incoming actor messages and use the ask pattern to work with the actor. If you don't mess things up intentionally, all methods will run from your actor-s EC.

Answer3: maybe write a macro function that would convert a trait to its Future-ized version? Like expanding this code:

MyTrickyMacro.futurize(underlying: SomeTrait)(ec)

to this:

class MacroGeneratedClass(underlying: SomeTrait)(implicit ec: ExecutionContext) {
  def add(i: Int) = Future(underlying.add(i))
  def subtract(i: Int) = Future(underlying.subtract(i))
}

Now, I think Answer1 is generally OK, but prone to errors and a bit of boilerplate. Answer2 still requires boilerplate code to be written, forces you to create case classes to contain function arguments and requires akka. And I didn't see any implementations Answer3.

So... Is there an easy way to do that?

VasiliNovikov
  • 9,681
  • 4
  • 44
  • 62
  • what about this.synchronized in scala – S.Karthik Sep 01 '17 at 13:24
  • @S.Karthik I was expecting this note. You _can_ do stuff using "lock-based concurrency", but my question is specifically about execution contexts. – VasiliNovikov Sep 01 '17 at 13:49
  • I think it would be tricky to do exactly what you want, because the code is normally not aware on which thread it runs, let alone if it runs on ExecutionContext. The cleanest way IMO would be Akka. But if you'd still try to implement the original idea, you'd have to make SomeTrait aware of the ExecutionContext. You can probably do it via macros, but I'd rather look into something less arcane, maybe dependent types? – Haspemulator Sep 01 '17 at 14:33
  • @Haspemulator agree, the "code" (methods and such) are generally not aware of the thread they will run on. So any kind of solution will do: code _convention_, macros etc. Speaking about dependent types -- I don't know how to decode the task using dependent types. IDK, no ideas. – VasiliNovikov Sep 01 '17 at 15:44

0 Answers0