Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save malzzz/9a70962e1e71caa8516b509b8e97d3df to your computer and use it in GitHub Desktop.
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.
//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