Forked from viktorklang/CallbackExecutionContext.scala
Created
October 31, 2017 14:22
-
-
Save malzzz/9a70962e1e71caa8516b509b8e97d3df to your computer and use it in GitHub Desktop.
Creates an ExecutionContext inside an Actor that will execute the runnables inside the Actor receive block, so that the risk of closing over Actor internals is less problematic.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Warning: Uses Akka internal APIs (not binary compatible), | |
//can be written not to depend on that but implemented like this for brevity. | |
package akka.util | |
trait CallbackExecutionContext { this: akka.actor.Actor ⇒ | |
// Defines our signal for callback execution | |
case object Execute | |
// ``SerializedSuspendableExecutionContext`` is Akka-internal | |
private[this] final val ssec: SerializedSuspendableExecutionContext = { | |
val d = this.context.dispatcher | |
val s = this.self | |
// The ``5`` is the throughput setting for the EC, e.g. the number of callbacks that will be | |
// executed per sweep, the parametrization of this is left as an exercise for the reader. | |
SerializedSuspendableExecutionContext(5 /*Chosen by fair dice roll*/)(new ExecutionContext { | |
override def execute(runnable: Runnable) = s ! Execute | |
override def reportFailure(t: Throwable) = d reportFailure t | |
}) | |
} | |
// This is the ``ExecutionContext`` that you'll use | |
final def callbackExecutionContext: ExecutionContext = ssec | |
// Must be used in the extending Actor's ``receive`` definition | |
def handleCallbacks: Receive = { | |
case Execute ⇒ ssec.run() | |
} | |
} | |
// Contrived example | |
class Foo extends Actor with CallbackExecutionContext { | |
var mutable = 0 | |
def receive = handleCallbacks orElse { | |
case "pigdog" => | |
implicit val ec = callbackExecutionContext | |
Future { if(mutable == 0) "Foo" else "Bar" } map { _.toUpperCase } map { | |
case "FOO" => mutable = 1 | |
case "BAR" => mutable = 0 | |
} foreach { _ => println("Current mutable: " + mutable)} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment