ActorsRing再び

現在の理解度で書き直してみた。(^^;

import scala.actors._
import scala.actors.Actor._

import java.lang.management._

object ActorsRing {
  val mxbean = ManagementFactory.getMemoryMXBean

  //------------------------------------------------
  class myactor(no:int, var neighbour:Actor, tail:Boolean) extends Actor {    
    def this(no:int, nb:Actor) = this(no, nb, false)
    
    def printstatus(start_time:Long, now:Long, counter:Int) = {
      val mem  = mxbean.getHeapMemoryUsage.getUsed /1024
      val time = (now - start_time) / 1000000000.0
      println(counter + ":" + time + "[sec], " + mem + "KB")
    }
    
    def act {
      loop {
        if (tail) {
          react {
            case ('Msg, counter:Int, start_time:Long) => {
              val now = System.nanoTime
              printstatus(start_time, now, counter)
              if (counter == 2) neighbour ! ('Stop, now)
              else              neighbour ! ('Msg, counter-1, now)
            }
            case ('Stop, start_time:Long) => {
              printstatus(start_time, System.nanoTime, 1)
              exit
            }
          }
        } else {
          react {
            case ('Msg, c:Int, st:Long) => neighbour ! ('Msg, c, st)
            case ('Stop, st:Long)       => neighbour ! ('Stop, st) ; exit
          }
        }
      }
    }
  }

  //------------------------------------------------
  def make_ring(n:int):List[myactor] = {
    val tail_a = new myactor(1, null, true)
    val chain = (2 to n).foldLeft(tail_a :: List[myactor]()) { (acc, i) =>
      val at = new myactor(i, acc.head)
      at :: acc
    }
    tail_a.neighbour = chain.head
    chain
  }

  //------------------------------------------------
  def time[A](f: => A):A = {
    val st = System.nanoTime
    val ret = f
    println((System.nanoTime()-st) / 1000000000.0 + "[sec]")
    println(mxbean.getHeapMemoryUsage.toString)
    ret
  }  
  
  //------------------------------------------------
  def main(args:Array[String]) {
    val num      = 100000
    val loop_num = 10
  
    println("START Main")
    println(mxbean.getHeapMemoryUsage.toString)
    println("----- Create Actors")
    val ring = time { make_ring(num) }
    println(ring.length + " Actors")
    println("----- Start Actors")
    time { ring.foreach { a => a.start } }
    println("----- Send first message")
    ring.head ! ('Msg, loop_num, System.nanoTime)
    println("END Main")
  }

(直接Actorとは関係ないけど)今日覚えたこと

引数が一つのメソッドは、method { .. }という形で呼び出せる

"xyz".substring{1}

その上で引数がcall-by-nameの場合([=> 型名]という型の場合)
引数の評価が遅延されるので、ブロックをメソッドに渡しているかのように扱える。

さらに引数がカリー化されてる場合

def f[X, Y, Z](x : => X)(y : => Y)(z : => Z) :X = {z; y; x}
f { println("A") } { println("B") } { println("C") }

こんな風にブロックを連ねて渡すことも可能
で、もともと

def time[A](f:Unit => A):A = {
  val st = System.nanoTime
  val ret = f()
  println((System.nanoTime()-st) / 1000000000.0 + "[sec]")
  println(mxbean.getHeapMemoryUsage.toString)
  ret
}

使いかたは

 time { Unit => ring.foreach { at => at.start } }

だったものが、上記のようになった