RemoteActor.select - result deterministic?

2020-07-30 04:21发布

问题:

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)
    } 
  }
}

回答1:

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).