Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Actors in Scala fail to process messages? (example in O'Reilly's Programming Scala)

Tags:

scala

actor

I'm completely new to Scala, and I've been working my way through Programming Scala (O'Reilly) online; while doing so, I was surprised by the result of the shapes-actor-script.scala example in Chapter 1, "A Taste Of Concurrency".

Specifically, the output of running scala -cp . shapes-actor-script.scala should be:

Circle.draw: Circle(Point(0.0,0.0),1.0)
Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,5.0)
Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0))
Error: Unknown message! 3.14159
exiting...

Yet about 10% of the time, I get no output at all, and even more rarely, I'll get only the first line as output. I don't know enough about Scala yet to know if this is normal due to the way Actors work, or if something might be wrong with my Scala installation (Scala 2.8.1 on Arch Linux).

Can Actors fail to process messages like this (perhaps because of the way the example is written)? Or is there something else going on that I might be missing here?


2 Answers

I believe the Scala REPL is using System.exit(...) when it is finished running the script. That will stop the process without waiting for any lingering threads.

That means that all messages will be sent to the actor, but the actor might not be able to handle them in time.

To demonstrate you might try to add Thread.sleep(1000) to each of the cases in the shapes-actor.scala:

case s: Shape => Thread.sleep(1000);s.draw()
case "exit"   => Thread.sleep(1000);println("exiting..."); exit
case x: Any   => Thread.sleep(1000);println("Error: Unknown message! " + x)

This will probably make the script fail every time (it does on my machine). If you then add Thread.sleep(5000) (giving 2 secs of slack) it should succeed every time.

The solution is to use a program that does not end in System.exit(...).

Update (seconds thoughts):

You can also set up the actor to notify on exit:

case "exit"   => Thread.sleep(1000);println("exiting..."); this.synchronized { this.notify }; exit

... and then the script can wait for the notification:

ShapeDrawingActor.synchronized { ShapeDrawingActor.wait(10000) }
like image 113
thoredge Avatar answered Dec 17 '25 02:12

thoredge


Sorry for the long delay in replying to this thread (since I wrote this example in the book :^/). I believe the real problem is that STDOUT isn't flushed by default on all OS (and shell?) environments and the behavior appears to differ depending on the version of Scala. This evening, I compiled and ran the code using 2.7.7. 2.8.0, and 2.8.1 on OS X (10.6.6), Java 1.6.0_24-b07-334-10M3326, and bash.

For 2.7.7 and 2.8.1, all the output was printed before the process exited. For 2.8.0, only some output appeared! When I added "System.out.flush" to the end of the shapes-actor-script.scala, all output was printed for 2.8.0.

like image 40
Dean Wampler Avatar answered Dec 17 '25 00:12

Dean Wampler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!