1

This is a problem from the chat I'm developing. There is a main/gui object with the main method, an Actor sender, that sends the messages and a empfänger, that receives them. The Problem is to make the empfänger use a function of the main/gui object to show the incoming messages. Because it didn't work, I simplified it, but I still didn't get the problem. May anyone tell my why this returns nothing at the terminal? What am I doing wrong?

import scala.actors._
object main_object {
    def infoterm(msg: String) = {
        println(msg)
    }
    def main(args: Array[String]) = {
    println("hallo")
    empfänger ! "foo"


    }
}


object empfänger extends Actor{
    var port = 50042
    var name = "local"
    var continuevar = true
    def foo(in: String) = {
        println("foo-empfänger" + in)
    }
    def act() {
        println("ydfjskj")
        test2.infoterm("tut")
        println("Empfänger gestartet")
        while(continuevar) {
            react {
                case msg:String  => {
                    println("empfänger" + msg)
                    test2.infoterm(msg)
                    foo("empfänger" + msg)
                }
            }
        }
    }
}

Thanks for you help, but I still don't get on. I modified like you told me but it's still not working.

Only by defining the Actor empfänger the whole program stops working, like this:

import scala.actors._
object test2 {
    def infoterm(msg: String) = {
        println(msg)
    }
    def main(args: Array[String]) = {
    println("hallo")
    }
}

object empfänger extends Actor{
    def act() {
        // test2.infoterm("tut")
        // println("Empfänger gestartet")
        loop {
            react {
                case msg:String  => {
                    if(msg == "Stop") exit()
                    else {
                    println("empfänger" + msg)
                    // test2.infoterm(msg)
                    }
                }
            }
        }
    }
}

What am I doing wrong?

3 Answers3

1

There are two ways from within an actor of looping upon receiving events:

  1. while-receive
  2. loop-react

You are using a mixture of the two (i.e. while-react). This simply cannot work for the following reasons:

receive

Receive blocks the current thread of execution waiting for a message to process. It can be used in a while-loop; although you should rarely use this as it ties an actor to a single thread - i.e. it is not scalable because you use 1 thread per actor.

react

Notice that the signature of the react method says that its return type is Nothing. This means that the method cannot terminate normally; it must either never return or throw an exception. In fact the latter happens; it uses exceptions as a flow-control mechanism, which only works when you use react inside loop (assuming you want to continually handle events). So your act method should look like this:

def act() {
  loop {
    react {
      case msg: String => 
    }
  }
}

It's well worth a look at the actor source code to see how the exception flow control works as it is a thing of beauty.

Error Messages: Linking actors

This is something I have struggled with for the actor framework. If an actor's reactions throw an exception, the actor exits and it's quite common to have no record of this is sys-out or sys-err. It can be extremely frustrating.

I strongly recommend linking canary actors to each system actor to listen for exits as follows:

def act() {
  import Actor._
  self link actor {
    case Exit(from, msg) => /* your logging here */
  }
  loop { ...
  }  
 }
}

However, this does not work in your case (again, extremely frustrating) because your whole act method throws an exception.

oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449
  • Certainly true that loop-react is *more* scalable than while-receive, but you can still have thousands of threads running on your average JVM (see this topic: http://stackoverflow.com/questions/763579/how-many-threads-can-a-java-vm-support - some guy got 200,000 threads running on Java 7 in 8 GB RAM). loop-react actors will also be limited by memory so I think it's best to express scalability as a scalar rather than a boolean... – Luigi Plinge May 18 '12 at 14:51
  • Thank, but I still don't get on. I modified like you told me but it's still not working. Only by – user1402050 May 19 '12 at 10:21
0

You're using a while loop inside the act method. The actor works asynchronously and gets activated, when it receives a message. Use loop {} instead of while and it should work. To stop an actor you have to send it a message like 'stop and react to it in your act method with exit.

drexin
  • 24,225
  • 4
  • 67
  • 81
0

Actors are not automagically started, that would be a bad thing. You have to explicitly call the 'start' method, ie, in your main() empänger.start()

Pia Kraft
  • 21
  • 1
  • the main point is, that empfänger doesn't need to be started to destroy the whole program. If you comment the object empfänger out "hallo" is printed, if you uncomment it, the program works. – user1402050 May 19 '12 at 13:07