|
Hi
I've just started using channels with actors and it appears that a channel has to be created while the body of its actor is running or there's no way to connect it to the actor. Is that right or am I missing something? Currently I can't see a way of creating a class that extends Actor and exposes Channels as fields (except using vars but that feels like a hack and is prone to race conditions unless you're careful). All the example code I've seen that uses channels shows the channels passed out of the actor by sending them as messages to other actors. Is this supposed to be the only way that channels can be used and if so why? Channel already has a constructor that takes an actor to use as its receiver but it's not public. Would it be possible to make it public or is there a reason why that wouldn't be a good idea? Thanks Chris |
|
Hi,
cjkent wrote: > I've just started using channels with actors and it appears that a channel > has to be created while the body of its actor is running or there's no way > to connect it to the actor. Is that right or am I missing something? > Currently I can't see a way of creating a class that extends Actor and > exposes Channels as fields (except using vars but that feels like a hack and > is prone to race conditions unless you're careful). > > All the example code I've seen that uses channels shows the channels passed > out of the actor by sending them as messages to other actors. Is this > supposed to be the only way that channels can be used and if so why? Channel > already has a constructor that takes an actor to use as its receiver but > it's not public. Would it be possible to make it public or is there a reason > why that wouldn't be a good idea? You are right that exchanging channel references is a bit clumsy that way. And it also does not add much to safety, either. So, I think it is a good idea to make the unary constructor of the Channel class public. Philipp |
|
I got bitten a few days ago by actor receive...the short version is that
I set up an actor, called into the Scala interpreter from within that actor supplying a local function (in the actor) as a callback. When the interpreter needs a line of input, it called my callback, where I have the actor's receive. The receive grabs a line of input from its message queue, then returns that to the interpreter. Overkill? Sure, but sometimes you just want to play with the neat actor facility. Except that it didn't work, and it was driving me nuts...I finally tracked it down...the first thing the Scala interpreter does on the _first_ line of input is use a _future_ to do the calculation...that resulted in the first invocation of my callback occurring on a thread that did not have the actor machinery set up, and led to no behavior. It's my understanding that an actor receive executed when the actor setup has not been performed will simply never return, and cannot be "unlocked". If that's the case, I believe that it would be appropriate to signal an error...or find a way to permit this to work correctly. When we're dealing with actors we don't want to have to think much about threads, and the requirement that the thread have actor setup performed somewhere up the stack is a bit painful -- particularly when the underlying library may engaged in thread-shifting behaviors of its own! Which brings up the sticky mess of lexical scoping vs. threading...what the actor library does, in effect, is say that in a given scope you might be executing in ay thread... RJ |
|
In lift, I go through great pains to make sure that Comet Actors get
messages that contain the functions that they need to execute (the callbacks that were linked to form elements, ajax elements, etc.) so the execution is always done in the scope of the Actor (within a receive/react.) There's nothing like a hybrid model to make one think about things like this! Judson, Ross wrote: > I got bitten a few days ago by actor receive...the short version is that > I set up an actor, called into the Scala interpreter from within that > actor supplying a local function (in the actor) as a callback. When the > interpreter needs a line of input, it called my callback, where I have > the actor's receive. The receive grabs a line of input from its message > queue, then returns that to the interpreter. Overkill? Sure, but > sometimes you just want to play with the neat actor facility. > > Except that it didn't work, and it was driving me nuts...I finally > tracked it down...the first thing the Scala interpreter does on the > _first_ line of input is use a _future_ to do the calculation...that > resulted in the first invocation of my callback occurring on a thread > that did not have the actor machinery set up, and led to no behavior. > > It's my understanding that an actor receive executed when the actor > setup has not been performed will simply never return, and cannot be > "unlocked". If that's the case, I believe that it would be appropriate > to signal an error...or find a way to permit this to work correctly. > When we're dealing with actors we don't want to have to think much about > threads, and the requirement that the thread have actor setup performed > somewhere up the stack is a bit painful -- particularly when the > underlying library may engaged in thread-shifting behaviors of its own! > > Which brings up the sticky mess of lexical scoping vs. threading...what > the actor library does, in effect, is say that in a given scope you > might be executing in ay thread... > > RJ > |
|
In reply to this post by Judson, Ross
"Judson, Ross" <[hidden email]> writes:
> Except that it didn't work, and it was driving me nuts...I finally > tracked it down...the first thing the Scala interpreter does on the > _first_ line of input is use a _future_ to do the calculation...that > resulted in the first invocation of my callback occurring on a thread > that did not have the actor machinery set up, and led to no behavior. Ah yes. :) You should set up the interpreter with -Xnojline. Then it will not do anything fancy like that. -Lex |
|
In reply to this post by Judson, Ross
Ross,
Judson, Ross wrote: > Except that it didn't work, and it was driving me nuts...I finally > tracked it down...the first thing the Scala interpreter does on the > _first_ line of input is use a _future_ to do the calculation...that > resulted in the first invocation of my callback occurring on a thread > that did not have the actor machinery set up, and led to no behavior. > > It's my understanding that an actor receive executed when the actor > setup has not been performed will simply never return, and cannot be > "unlocked". It is actually possible to use send/receive from a thread that is not set up as an actor. Here is an (executable) example: import scala.actors.Actor import scala.actors.Actor._ object threads extends Application { val a = actor { receive { case other: Actor => other ! 'hello receive { case any => println("response: "+any) } } } val t = new Thread(new Runnable { def run() { a ! self receive { case 'hello => println("got 'hello") sender ! 'world } } }) t.start() } In this example, `t' is able to send its (lazily created) actor identity, `self', to actor `a'. After that it can receive messages as if it was a normal actor. What you cannot do is sending a message directly to the thread as in `t ! msg'. Currently, there is no implicit conversion defined that would turn a `Thread' into a `RichThread' with this method. You cannot obtain a thread's actor identity "from outside" either, as in `t.self'. So, currently a thread itself needs to invoke `self', and pass it on to other actors, before it can engage in actor communication. > If that's the case, I believe that it would be appropriate > to signal an error...or find a way to permit this to work correctly. So, one could indeed signal an error when a non-actor thread calls `receive' without having called `self' before, since there is no way other actors could find out its actor identity, and therefore there is no way it could receive messages. Alternatively, one could provide a way to obtain a thread's actor identity "from outside" which could even be done using an implicit conversion I believe. > Which brings up the sticky mess of lexical scoping vs. threading...what > the actor library does, in effect, is say that in a given scope you > might be executing in ay thread... I am not sure what you mean exactly, but I'd like to point out that (even if this is no news for you I mention it anyway since it might be interesting for other readers and provide a basis for further discussion) one important motivation for actors is that they allow you to avoid control inversion meaning that there is at most one thread executing inside an actor at a time, and the user chooses when this is going to happen by writing a straight-line program that waits for messages at explicit points in the control flow. In this model, one usually wants to avoid passing callback functions out to other threads that invoke them asynchronously; instead, other threads should interact with an actor only by sending messages to it. If callback-like behavior is wanted then the following pattern achieves it in a thread-safe manner: def eventloop() { react { case Event1 => // handle Event1 eventloop() ... case Eventn => // handle Eventn eventloop() } } This pattern is provided as an abstract operation in `Actor.eventloop': import scala.actors.Actor._ eventloop { case Event1 => // handle Event1 case Eventn => // handle Eventn } Note that there is no need for tail calls to some enclosing function any more. Coming back to the threads interaction business, I think it would be helpful to look at concrete example code, so that we can discuss concrete solutions. Cheers, Philipp |
| Powered by Nabble | Edit this page |
