alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Akka/Scala example source code file (Creators.scala)

This example Akka source code file (Creators.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Akka and Scala source code examples by using tags.

All credit for the original source code belongs to akka.io; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Akka tags/keywords

actor, actorref, actorreffactory, akka, classtag, collection, concurrent, mutable, option, receive, reflection, string, t, throwable, time, unit

The Creators.scala Akka example source code

/**
 * Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
 */

package akka.actor.dsl

import scala.concurrent.Await
import akka.actor._
import scala.collection.immutable.TreeSet
import scala.concurrent.duration._
import scala.collection.mutable.Queue
import akka.util.Timeout
import java.util.concurrent.TimeoutException
import java.util.concurrent.atomic.AtomicInteger
import akka.pattern.ask
import scala.reflect.ClassTag

trait Creators { this: ActorDSL.type ⇒

  /**
   * This trait provides a DSL for writing the inner workings of an actor, e.g.
   * for quickly trying things out in the REPL. It makes the following keywords
   * available:
   *
   *  - `become` mapped to `context.become(_, discardOld = true)`
   *
   *  - `becomeStacked` mapped to `context.become(_, discardOld = false)`
   *
   *  - `unbecome` mapped to `context.unbecome`
   *
   *  - `setup` for implementing `preStart()`
   *
   *  - `whenFailing` for implementing `preRestart()`
   *
   *  - `whenRestarted` for implementing `postRestart()`
   *
   *  - `teardown` for implementing `postStop`
   *
   * Using the life-cycle keywords multiple times results in replacing the
   * content of the respective hook.
   */
  trait Act extends Actor {

    private[this] var preStartFun: () ⇒ Unit = null
    private[this] var postStopFun: () ⇒ Unit = null
    private[this] var preRestartFun: (Throwable, Option[Any]) ⇒ Unit = null
    private[this] var postRestartFun: Throwable ⇒ Unit = null
    private[this] var strategy: SupervisorStrategy = null

    /**
     * @see [[akka.actor.OneForOneStrategy]]
     */
    def OneForOneStrategy = akka.actor.OneForOneStrategy

    /**
     * @see [[akka.actor.AllForOneStrategy]]
     */
    def AllForOneStrategy = akka.actor.AllForOneStrategy

    /**
     * @see [[akka.actor.SupervisorStrategy]]
     */
    def Stop = SupervisorStrategy.Stop

    /**
     * @see [[akka.actor.SupervisorStrategy]]
     */
    def Restart = SupervisorStrategy.Restart

    /**
     * @see [[akka.actor.SupervisorStrategy]]
     */
    def Resume = SupervisorStrategy.Resume

    /**
     * @see [[akka.actor.SupervisorStrategy]]
     */
    def Escalate = SupervisorStrategy.Escalate

    /**
     * Add the given behavior on top of the behavior stack for this actor. This
     * stack is cleared upon restart. Use `unbecome()` to pop an element off
     * this stack.
     */
    def becomeStacked(r: Receive) = context.become(r, discardOld = false)

    /**
     * Replace the behavior at the top of the behavior stack for this actor. The
     * stack is cleared upon restart. Use `unbecome()` to pop an element off
     * this stack or `becomeStacked()` to push a new element on top of it.
     */
    def become(r: Receive) = context.become(r, discardOld = true)

    /**
     * Pop the active behavior from the behavior stack of this actor. This stack
     * is cleared upon restart.
     */
    def unbecome(): Unit = context.unbecome()

    /**
     * Set the supervisor strategy of this actor, i.e. how it supervises its children.
     */
    def superviseWith(s: SupervisorStrategy): Unit = strategy = s

    /**
     * Replace the `preStart` action with the supplied thunk. Default action
     * is to call `super.preStart()`
     */
    def whenStarting(body: ⇒ Unit): Unit = preStartFun = () ⇒ body

    /**
     * Replace the `preRestart` action with the supplied function. Default
     * action is to call `super.preRestart()`, which will kill all children
     * and invoke `postStop()`.
     */
    def whenFailing(body: (Throwable, Option[Any]) ⇒ Unit): Unit = preRestartFun = body

    /**
     * Replace the `postRestart` action with the supplied function. Default
     * action is to call `super.postRestart` which will call `preStart()`.
     */
    def whenRestarted(body: Throwable ⇒ Unit): Unit = postRestartFun = body

    /**
     * Replace the `postStop` action with the supplied thunk. Default action
     * is to call `super.postStop`.
     */
    def whenStopping(body: ⇒ Unit): Unit = postStopFun = () ⇒ body

    override def preStart(): Unit = if (preStartFun != null) preStartFun() else super.preStart()
    override def preRestart(cause: Throwable, msg: Option[Any]): Unit = if (preRestartFun != null) preRestartFun(cause, msg) else super.preRestart(cause, msg)
    override def postRestart(cause: Throwable): Unit = if (postRestartFun != null) postRestartFun(cause) else super.postRestart(cause)
    override def postStop(): Unit = if (postStopFun != null) postStopFun() else super.postStop()
    override def supervisorStrategy: SupervisorStrategy = if (strategy != null) strategy else super.supervisorStrategy

    /**
     * Default behavior of the actor is empty, use `become` to change this.
     */
    override def receive: Receive = Actor.emptyBehavior
  }

  /**
   * Use this trait when defining an [[akka.actor.Actor]] with [[akka.actor.Stash]],
   * since just using `actor()(new Act with Stash{})` will not be able to see the
   * Stash component due to type erasure.
   */
  trait ActWithStash extends Act with Stash

  private def mkProps(classOfActor: Class[_], ctor: () ⇒ Actor): Props =
    Props(classOf[TypedCreatorFunctionConsumer], classOfActor, ctor)

  /**
   * Create an actor from the given thunk which must produce an [[akka.actor.Actor]].
   *
   * @param ctor is a by-name argument which captures an [[akka.actor.Actor]]
   *        factory; <b>do not make the generated object accessible to code
   *        outside and do not return the same object upon subsequent invocations.</b>
   * @param factory is an implicit [[akka.actor.ActorRefFactory]], which can
   *        either be an [[akka.actor.ActorSystem]] or an [[akka.actor.ActorContext]],
   *        where the latter is always implicitly available within an [[akka.actor.Actor]].
   */
  def actor[T <: Actor: ClassTag](ctor: ⇒ T)(implicit factory: ActorRefFactory): ActorRef = {
    // configure dispatcher/mailbox based on runtime class
    val classOfActor = implicitly[ClassTag[T]].runtimeClass
    val props = mkProps(classOfActor, () ⇒ ctor)
    factory.actorOf(props)
  }

  /**
   * Create an actor from the given thunk which must produce an [[akka.actor.Actor]].
   *
   * @param name is the name, which must be unique within the context of its
   *        parent.
   * @param ctor is a by-name argument which captures an [[akka.actor.Actor]]
   *        factory; <b>do not make the generated object accessible to code
   *        outside and do not return the same object upon subsequent invocations.</b>
   * @param factory is an implicit [[akka.actor.ActorRefFactory]], which can
   *        either be an [[akka.actor.ActorSystem]] or an [[akka.actor.ActorContext]],
   *        where the latter is always implicitly available within an [[akka.actor.Actor]].
   */
  def actor[T <: Actor: ClassTag](name: String)(ctor: ⇒ T)(implicit factory: ActorRefFactory): ActorRef = {
    // configure dispatcher/mailbox based on runtime class
    val classOfActor = implicitly[ClassTag[T]].runtimeClass
    val props = mkProps(classOfActor, () ⇒ ctor)

    if (name == null) factory.actorOf(props)
    else factory.actorOf(props, name)
  }

  /**
   * Create an actor from the given thunk which must produce an [[akka.actor.Actor]].
   *
   * @param name is the name, which must be unique within the context of its
   *        parent; defaults to `null` which will assign a name automatically.
   * @param ctor is a by-name argument which captures an [[akka.actor.Actor]]
   *        factory; <b>do not make the generated object accessible to code
   *        outside and do not return the same object upon subsequent invocations.</b>
   * @param factory is an implicit [[akka.actor.ActorRefFactory]], which can
   *        either be an [[akka.actor.ActorSystem]] or an [[akka.actor.ActorContext]],
   *        where the latter is always implicitly available within an [[akka.actor.Actor]].
   */
  def actor[T <: Actor: ClassTag](factory: ActorRefFactory, name: String)(ctor: ⇒ T): ActorRef =
    actor(name)(ctor)(implicitly[ClassTag[T]], factory)

  /**
   * Create an actor with an automatically generated name from the given thunk
   * which must produce an [[akka.actor.Actor]].
   *
   * @param ctor is a by-name argument which captures an [[akka.actor.Actor]]
   *        factory; <b>do not make the generated object accessible to code
   *        outside and do not return the same object upon subsequent invocations.</b>
   * @param factory is an implicit [[akka.actor.ActorRefFactory]], which can
   *        either be an [[akka.actor.ActorSystem]] or an [[akka.actor.ActorContext]],
   *        where the latter is always implicitly available within an [[akka.actor.Actor]].
   */
  def actor[T <: Actor: ClassTag](factory: ActorRefFactory)(ctor: ⇒ T): ActorRef =
    actor(null: String)(ctor)(implicitly[ClassTag[T]], factory)

}

Other Akka source code examples

Here is a short list of links related to this Akka Creators.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.