Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add scala actors to an existing program without interfering with the normal termination behavior?

This program, after executing main(), does not exit.

object Main
{
    def main(args: Array[String]) {
        ... // existing code
        f()
        ... // existing code
    }
    def f() {
        import scala.actors.Actor._
        val a = actor {
            loop {
                react {
                case msg: String => System.out.println(msg)
                }
            }
        }
        a ! "hello world"
    }
}

Because of this unexpected side-effect, using actors can be viewed as intrusive.

Assuming the actors must continue to run until program termination, how would you do to preserve original behavior in all cases of termination?

like image 862
Eldritch Conundrum Avatar asked Feb 21 '10 11:02

Eldritch Conundrum


2 Answers

In 2.8 there's a DaemonActor class that allows this. In 2.7.x I you could hack in a custom scheduler that doesn't prevent shutdown even if there are still live actors, or if you want an easy way you could call System.exit() at the end of main.

If you think of an actor as kind of a light-weight thread, much of the time you want a live actor to prevent program termination. Otherwise if you have a program that does all of its work in actors, you'd need to have something on the main thread just to keep it alive until all the actors finish.

like image 200
Erik Engbrecht Avatar answered Nov 06 '22 03:11

Erik Engbrecht


After the main thread in the above example completed, the program still had a non-daemon thread running the actor. It is usually a bad idea to brutally terminate running threads using Thread.destroy() or System.exit() for results may be very bad for your program including, but not limited to, data corruption and deadlocks. That is why Thread.destroy() and alike methods were deprecated in Java for the first place. The right way would be to explicitly implement termination logic in your threads. In case of Scala actors that boils down to sending a Stop message to all running actors and make them quit when they get it. With this approach your eample would look like this:

object Main
{
    case object Stop
    def main(args: Array[String]) {
        ... // existing code
        val a = f()
        a ! "hello world"
        ... // existing code
        a ! Stop
    }
    def f() = {
        import scala.actors.Actor._
        actor {
            loop {
                react {
                   case msg: String => System.out.println(msg)
                   case Stop => exit()
                }
            }
        }
    }
}
like image 45
Maxim Vladimirsky Avatar answered Nov 06 '22 05:11

Maxim Vladimirsky