#1082 Actors in JS?

rfeldman Sat 24 Apr 2010

Just read up on Actors to get my animation groove on using FWT with JavaScript. Tried a modification of a few examples I found and ended up here:

Void main()
{  
  Label label := Label { text = "Time Displays Here"; halign=Halign.center }

  pool := ActorPool()

  a := Actor(pool) |Obj msg| { label.text = "$Time.now: $msg" }
  a.send("start")
  a.sendLater(1sec, "1sec")
  a.sendLater(3sec, "3sec")
  a.sendLater(2sec, "2sec")
  Actor.sleep(5sec)    

  Window
  {
    size = Size(300,200)
    label,
  }.open
}

Only problem is, running this in a browser I get this JS error: fan.sys.ActorPool.make is not a function.

What am I doing wrong?

andy Sat 24 Apr 2010

Current JavaScript VMs are single-threaded - so its not yet possible to do concurrent programming in the browser like we support on the JVM and CLR.

WebWorkers are the emerging standard for asynchronous programming in JavaScript. However its a much more constrained API than Java/C#. Which is good if you're writing JavaScript (very clear and simple on how state is shared). But not the best model for trying to map Fantom into.

I haven't taken a deep dive to see exactly how things will work - so we haven't really discussed what things might look like. One major issue is how do you fallback if Web Workers are not supported? Is that even feasible?

The other two are (1) how is code efficiently loaded into workers, and (2) what impact does the worker message passing restrictions have on the Actor API and Fantom const model.

Might be worth looking into more tho - since even if its not supported by all the browsers yet, would be nice to lock down the design.

rfeldman Sun 25 Apr 2010

Hm, interesting...food for thought: a potential workaround if WebWorkers are not available might be (haven't really thought this through very thoroughly) to approximate time slices by wrapping each statement in a thread inside a call to setTimeout(1). No idea what that might look like performance-wise, and there are probably a lot of synchronization and state-sharing issues I am overlooking, but food for thought maybe?

At any rate, in the meantime is there some workaround I could use to wrap JavaScript's setTimeout method? That's all I really need for FWT animation in both a browser and a desktop app. I didn't see any support for JS natives in the doc, though an easy workaround would be a method that detects if the compilation target is JS and executes a native setTimeout if so, and defaults to an Actor-based invocation if not.

Anything like that sound possible?

andy Sun 25 Apr 2010

a potential workaround if WebWorkers are not available might be (haven't really thought this through very thoroughly) to approximate time slices by wrapping each statement in a thread inside a call to setTimeout(1)

I had considered that - tho not sure how well it would work out in practice. Been thinking lately that its just not supported. And its up to the developer to choose the tradeoff of features/browser support.

At any rate, in the meantime is there some workaround I could use to wrap JavaScript's setTimeout method

We won't ever support that in the standard API - but you can easily add it using a JavaScript native:

// Foo.fan
class Foo 
{  
  static native Void setTimeout(Duration dur, |->| callback)
}

// FooPeer.js
fan.<podName>.FooPeer = fan.sys.Obj.$extend(fan.sys.Obj);
fan.<podName>.FooPeer.prototype.$ctor = function(self) {}
fan.<podName>.FooPeer.setTimeout = function(dur, callback)
{
  var d = dur.toMillis();
  var f = function() { callback.call(); }
  setTimeout(f,d);
}

// make sure you add js native dir in build.fan
jsDirs  = [`js/`]

rfeldman Sun 25 Apr 2010

Gotcha - that makes sense. Thanks for the help! By the way, you guys are phenomenal about responding on here - it feels like James Gosling is answering my newbie language questions. Very awesome.

I have another question related to animation in FWT, but I'll start a new topic for organization's sake.

Login or Signup to reply.