igx
igx

Reputation: 4231

akka closing over sender

Trying to understand if the following use of sender are safe. I saw on some posts that closing over the sender is unsafe but if the call is by value, the sender() is evaluated when the method is called, correct? are the following patterns safe?

1.

context.system.scheduler.scheduleOnce(1 second, self, "foo")(executor = context.dispatcher, sender = sender())

2.

def receive: Receive = {
    case "Process" => context.become(processing(sender())
}
def processing(replyTo: ActorRef): receive = {...}

3.

def receive: Receive = {
case "Process" => 
context.actorOf(Props(new FooActor(replyTo = sender())))
}

Upvotes: 2

Views: 544

Answers (1)

Rich
Rich

Reputation: 15448

When people say "closing" over the sender() function, they mean capturing the "this" reference into a lambda so that sender() will be called at a later time. This is not safe, because the value returned by sender() at a later time will not be the same as the value it currently has. If you capture (or "close over") the value currently returned by sender(), that is fine.

It is not always clear whether you are capturing sender() as a function or sender() as a value, because it will vary depending on whether you pass it to a call-by-value or a call-by-name function, as you have pointed out.

As Viktor points out in his comment:

1 and 2 are fine, because you are capturing the current value of sender().

3 is not safe, because "Props.apply" is a pass-by-name function, so you have inadvertently closed over sender() as a function rather than as a value.

I am not aware of any easy way to distinguish between these two cases, other than checking the docs (or clicking through in your IDE, if it supports it).

Upvotes: 2

Related Questions