Commits

Ivan Inozemtsev committed be81593

added pi calc on actors

  • Participants
  • Parent commits 6c222e5

Comments (0)

Files changed (2)

     podName = "snippets"
     summary = ""
     srcDirs = [`fan/`]
-    depends = ["sys 1.0", "concurrent 1.0"]
+    depends = ["sys 1.0", "concurrent 1.0",
+      "build 1.0", "web 1.0"]
   }
 }
+using concurrent
+
+const class Master : Actor 
+{
+  new make(Actor listener, Int workerCount, 
+    Int messageCount, 
+    Int elementCount, ActorPool pool) : super(pool)
+  {
+    workers = (0..workerCount).map { Worker(this, pool) }
+    this.messageCount = messageCount
+    this.elementCount = elementCount
+    this.listener = listener
+  }
+  const Int messageCount
+  const Int elementCount
+  private const Actor listener
+  private const Worker[] workers
+  
+  override Obj? receive(Obj? msg)
+  {
+    if(msg == "start") //start over
+    {
+      pi = 0.0f
+      resultCount = 0
+      start = Duration.now
+      
+      messageCount.times |i| 
+      { 
+        workers[i % workers.size].send([i * elementCount, elementCount])
+      }
+      return null
+    }
+    
+    if(msg == "isDone") return resultCount == messageCount
+    
+    if(msg isnot Float) return null
+    
+    pi += (Float)msg
+    resultCount++
+    if(resultCount == messageCount) listener.send([pi, Duration.now - start])
+    
+    return null
+  }
+  
+  private Float pi 
+  {
+    get { Actor.locals["pi"] }
+    set { Actor.locals["pi"] = it }
+  }
+  
+  private Int resultCount 
+  {
+     get { Actor.locals["resultCount"] }
+     set { Actor.locals["resultCount"]= it }
+  }
+  
+  private Duration start
+  {
+    get { Actor.locals["start"] }
+    set { Actor.locals["start"] = it }
+  }
+}
+
+const class Worker : Actor
+{
+  const Master master
+  new make(Master master, ActorPool pool) : super(pool) 
+  {
+    this.master = master 
+  }
+  
+  override Obj? receive(Obj? msg)
+  {
+    if(msg isnot Int[] || msg->size != 2) { throw ArgErr("Send [start, count] as msg") }
+    Int start := msg->first
+    Int count := msg->last
+    
+    result := (start..<start+count)
+      .map { 4.0f * (1 - (it % 2) * 2 )/(2*it + 1) }
+      .reduce(0.0f) |r, v| { r->plus(v) }
+    
+    master.send(result)
+    
+    return null
+  }
+}
+
+class Pi
+{
+  Void main()
+  {
+    pool := ActorPool()
+    listener := Actor(pool) |Obj? msg| {
+      echo("Pi is ${msg->first}")
+      echo("Calc time is ${msg->last->toMillis}ms")
+    }
+    
+    master := Master(listener, 4, 10000, 10000, pool)
+    master.send("start")
+    
+    while(!master.send("isDone").get)
+    {
+      Actor.sleep(100ms)
+    }
+  }
+}