I wonder if there is any determinism when calling val delegate = RemoteActor.select(). I'm asking this, because I noticed that the program doesn't terminate, when I'm sending delegates over the net.
Are there any other side effects, which depend on the delegate?
Are there any rules, when RemoteActor.select will return the same delegate for the same arguments?
Here's some example code which demonstrates the RemoteActor.select problem:
package test
import scala.actors.Actor, Actor._
import scala.actors.remote._, RemoteActor._
object DelegateTest {
def main(args :Array[String]) {
val actor = new Actorlein("localhost", 63000, 'first)
actor ! 'eval
}
}
class Actorlein(val host: String, val port: Int, val symbol: Symbol) extends Actor {
val preProxy1 = select(node, symbol)
val preProxy2 = select(node, symbol)
val node = Node(host,port)
this.start
alive(port)
register(symbol, this)
val initProxy1 = select(node, symbol)
val initProxy2 = select(node, symbol)
override def act = {
val actProxy1 = select(node, symbol)
val actProxy2 = select(node, symbol)
react {
case 'eval => {
val reactProxy1 = select(node, symbol)
val reactProxy2 = select(node, symbol)
//all true
println("pProxy equal? "+(preProxy1 == preProxy2))
println("iProxy equal? "+(initProxy1 == initProxy2))
println("aProxy equal? "+(actProxy1 == actProxy2))
println("rProxy equal? "+(reactProxy1 == reactProxy2))
//all true()
println("i equal p? "+(initProxy1 == preProxy1)) //false
println("r equal p? "+(reactProxy1 == preProxy1))//false
println("a equal p? "+(actProxy1 == preProxy1)) //false
println("i equal a? "+(initProxy1 == actProxy1)) //false
println("r equal a? "+(reactProxy1 == actProxy1))//true
}
case any => println("Unkown Msg: "+any)
}
}
}
Your question got me curious so I had a quick look at the source ... here's what I found:
What select returns seems to depend on an object that handles the TCP connections. As this NetKernel remembers previously created proxies, the proxies are the same as long as the "current Netkernel" is the same. The current Netkernel depends on the current value of Actor.self, which might (I didn't dig that deep) on the current thread. For me that explains why r=a but p and i are different from that.
I guess, the reason for p and i being different is that a new NetKernel is associated with the actor by the alive(port) call (the actor's kernel needs to use the specified port, and not a random one).