Code Examples for

Actors in Scala

Return to chapter index

5 Event-Based Programming

  • 5.1 Events versus threads
  • 5.2 Making actors event-based: react
  • 5.3 Event-based futures
  • 5.1 Events versus threads

    5.2 Making actors event-based: react


    def buildChain(size: Int, next: Actor): Actor = { val a = actor { react { case 'Die => val from = sender if (next != null) { next ! 'Die react { case 'Ack => from ! 'Ack } } else from ! 'Ack } } if (size > 0) buildChain(size - 1, a) else a }
    def main(args: Array[String]) { val numActors = args(0).toInt val start = System.currentTimeMillis buildChain(numActors, null) ! 'Die receive { case 'Ack => val end = System.currentTimeMillis println("Took " + (end - start) + " ms") } }
    actor { react { case "hello" => println("hi") } println("finished") }
    actor { react { case "hello" => println("hi") println("finished") } }
    def waitFor(n: Int): Unit = if (n > 0) { react { case 'Die => val from = sender if (next != null) { next ! 'Die react { case 'Ack => from ! 'Ack; waitFor(n - 1) } } else { from ! 'Ack; waitFor(n - 1) } } }
    def sleep(delay: Long) { register(timer, delay, self) react { case 'Awake => /* OK, continue */ } }
    actor { val period = 1000 { // code before going to sleep sleep(period) } andThen { // code after waking up } }
    def buildChain(size: Int, next: Actor, lives: Int): Actor = { val a = actor { var n = lives loopWhile (n > 0) { n -= 1 react { case 'Die => val from = sender if (next != null) { next ! 'Die react { case 'Ack => from ! 'Ack } } else from ! 'Ack } } } if (size > 0) buildChain(size - 1, a, lives) else a }

    5.3 Event-based futures


    def renderImages(url: String) { val imageInfos = scanForImageInfo(url) val dataFutures = for (info <- imageInfos) yield { val loader = actor { react { case Download(info) => reply(info.downloadImage()) } } loader !! Download(info) } for (i <- 0 until imageInfos.size) { dataFutures(i)() match { case data @ ImageData(_) => renderImage(data) } } println("OK, all images rendered.") }
    def renderImages(url: String) { val imageInfos = scanForImageInfo(url) val dataFutures = for (info <- imageInfos) yield { val loader = actor { react { case Download(info) => reply(info.downloadImage()) } } loader !! Download(info) } var i = 0 loopWhile (i < imageInfos.size) { i += 1 dataFutures(i-1).inputChannel.react { case data @ ImageData(_) => renderImage(data) } } andThen { println("OK, all images rendered.") } }
    def renderImages(url: String) { val imageInfos = scanForImageInfo(url) val dataFutures = for (info <- imageInfos) yield { val loader = actor { react { case Download(info) => reply(info.downloadImage()) } } loader !! Download(info) } { for (ft <- ForEach(dataFutures)) { ft.inputChannel.react { case data @ ImageData(_) => renderImage(data) } } } andThen { println("OK, all images rendered.") } }
    case class ForEach[T](iter: Iterable[T]) { def foreach(fun: T => Unit): Unit = { val it = iter.elements loopWhile (it.hasNext) { fun(it.next) } } }

    For more information about Actors in Scala, please visit:

    http://www.artima.com/shop/actors_in_scala

    and:

    http://booksites.artima.com/actors_in_scala

    Copyright © 2011 Artima, Inc. All rights reserved.

    Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.