Is it safe to call "self" from within an Actor instance but not on a thread managed by the Akka system?

455 views
Skip to first unread message

oxbow_lakes

unread,
May 25, 2012, 11:50:38 AM5/25/12
to akka...@googlegroups.com
I'm looking at migrations of scala actors onto akka ones. One (very) common paradigm I've used is the wrapping of an external callback-style API within an actor. That is, my actor class has some method in it which is called by (a Thread managed by) the external API:

def apiCallback(e: ApiEvent) { this ! e }

So I simply pipe the event onto the mailbox of my actor. Obviously this exact snippet is not valid in Akka because "this" is not an ActorRef. I had *assumed* that it was *not* safe to replace "this" with "self" because it was not safe to use self from some thread not managed by Akka. But from playing around, this does not seem to be the case (i.e. it works just fine). However, I cannot find any documentation to the extent that it is always safe to call "self" from any thread. However, looking at the code, it's a val, so I presume that it is just fine. Can someone confirm?

Cheers,
Chris

√iktor Ҡlang

unread,
May 25, 2012, 11:56:16 AM5/25/12
to akka...@googlegroups.com
On Fri, May 25, 2012 at 5:50 PM, oxbow_lakes <oxbow...@gmail.com> wrote:
I'm looking at migrations of scala actors onto akka ones. One (very) common paradigm I've used is the wrapping of an external callback-style API within an actor. That is, my actor class has some method in it which is called by (a Thread managed by) the external API:

def apiCallback(e: ApiEvent) { this ! e }

Problem is that if you close over self, you implcitly close over "this", which ay point to an old instance of the actor if it has been restarted since.
so in these cases, just assign a val to self before and refer to the val instead, to avoid the capture.
 

So I simply pipe the event onto the mailbox of my actor. Obviously this exact snippet is not valid in Akka because "this" is not an ActorRef. I had *assumed* that it was *not* safe to replace "this" with "self" because it was not safe to use self from some thread not managed by Akka. But from playing around, this does not seem to be the case (i.e. it works just fine). However, I cannot find any documentation to the extent that it is always safe to call "self" from any thread. However, looking at the code, it's a val, so I presume that it is just fine. Can someone confirm?

Considered confirmed?

Cheers,
 

Cheers,
Chris

--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/vnE6bSvIU1EJ.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.



--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

√iktor Ҡlang

unread,
May 25, 2012, 12:10:29 PM5/25/12
to akka...@googlegroups.com
Speaking of which, it would be nice with a @closebyvalue annotation to let the scala compiler sort it out.

Cheers,

oxbow_lakes

unread,
May 25, 2012, 12:16:11 PM5/25/12
to akka...@googlegroups.com
No - I didn't really understand that reply. Can you give me an example of when this would not work? (Isn't the ActorRef an entity which remains "constant", even if the instances are created and destroyed?)


On Friday, 25 May 2012 16:56:16 UTC+1, √ wrote:
On Fri, May 25, 2012 at 5:50 PM, oxbow_lakes <oxbow...@gmail.com> wrote:
I'm looking at migrations of scala actors onto akka ones. One (very) common paradigm I've used is the wrapping of an external callback-style API within an actor. That is, my actor class has some method in it which is called by (a Thread managed by) the external API:

def apiCallback(e: ApiEvent) { this ! e }

Problem is that if you close over self, you implcitly close over "this", which ay point to an old instance of the actor if it has been restarted since.
so in these cases, just assign a val to self before and refer to the val instead, to avoid the capture.
 

So I simply pipe the event onto the mailbox of my actor. Obviously this exact snippet is not valid in Akka because "this" is not an ActorRef. I had *assumed* that it was *not* safe to replace "this" with "self" because it was not safe to use self from some thread not managed by Akka. But from playing around, this does not seem to be the case (i.e. it works just fine). However, I cannot find any documentation to the extent that it is always safe to call "self" from any thread. However, looking at the code, it's a val, so I presume that it is just fine. Can someone confirm?

Considered confirmed?

Cheers,
 

Cheers,
Chris

--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/vnE6bSvIU1EJ.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.

oxbow_lakes

unread,
May 25, 2012, 12:23:30 PM5/25/12
to akka...@googlegroups.com
"just assign a val to self before and refer to the val instead"

"Before" in the method, or in the class? 

Option1

def apiCallback(e: ApiEvent) { val me = self; me ! e } 

Option 2

val me = self
def apiCallback(e: ApiEvent) { me ! e } 

If self is a val itself, how can this make any difference?


On Friday, 25 May 2012 16:56:16 UTC+1, √ wrote:

Problem is that if you close over self, you implcitly close over "this", which ay point to an old instance of the actor if it has been restarted since.
so in these cases, just assign a val to self before and refer to the val instead, to avoid the capture.

√iktor Ҡlang

unread,
May 25, 2012, 12:25:45 PM5/25/12
to akka...@googlegroups.com
On Fri, May 25, 2012 at 6:23 PM, oxbow_lakes <oxbow...@gmail.com> wrote:
"just assign a val to self before and refer to the val instead"

"Before" in the method, or in the class? 

Option1

def apiCallback(e: ApiEvent) { val me = self; me ! e } 

This is short for:

def apiCallback(e: ApiEvent) { val me = outer.this.self; me ! e }

i.e. it is capturing the outer class's "this"-reference
 

Option 2

val me = self
def apiCallback(e: ApiEvent) { me ! e } 

If self is a val itself, how can this make any difference?

This is merely closing over a local, so it doesn't need or can close over the outer this pointer.

Cheers,
 


On Friday, 25 May 2012 16:56:16 UTC+1, √ wrote:

Problem is that if you close over self, you implcitly close over "this", which ay point to an old instance of the actor if it has been restarted since.
so in these cases, just assign a val to self before and refer to the val instead, to avoid the capture.

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/yG2e-FajXOEJ.

To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.



--
Viktor Klang

Akka Tech Lead

oxbow_lakes

unread,
May 25, 2012, 12:37:58 PM5/25/12
to akka...@googlegroups.com
I still don't understand the difference. In the code:

val me = self
def apiCallback(e: ApiEvent) { me ! e } 

me is an "instance variable" - so I am still doing "outer.this.me" aren't I? In any case, won't the value of "self" from the "old" instance still be the "correct" ActorRef?

Chris
To unsubscribe from this group, send email to akka-user+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.

√iktor Ҡlang

unread,
May 25, 2012, 12:46:59 PM5/25/12
to akka...@googlegroups.com

I assumed 'me' as a local variable, i.e. not a member.

Cheers,
V

To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/8-h86cyXsiwJ.

To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.

Scott Parish

unread,
May 25, 2012, 1:03:03 PM5/25/12
to akka...@googlegroups.com
On Fri, May 25, 2012 at 10:50 AM, oxbow_lakes <oxbow...@gmail.com> wrote:
I'm looking at migrations of scala actors onto akka ones. One (very) common paradigm I've used is the wrapping of an external callback-style API within an actor. That is, my actor class has some method in it which is called by (a Thread managed by) the external API:

def apiCallback(e: ApiEvent) { this ! e }

I've been writing something like the following, which is similarish to what i've seen done a lot in erlang wrapping the gen_server:call():

class Something(implicit context: ActorContext) {
   val actor = context.actorOf(Props(new SomethingActor))

  def apiCallback(e: ApiEvent) { actor ! e }

   class SomethingActor extends Actor {
      ...actor code here...
   }

Roland Kuhn

unread,
May 25, 2012, 1:06:47 PM5/25/12
to akka...@googlegroups.com, akka...@googlegroups.com


On 25 maj 2012, at 18:37, oxbow_lakes <oxbow...@gmail.com> wrote:

I still don't understand the difference. In the code:

val me = self
def apiCallback(e: ApiEvent) { me ! e } 

me is an "instance variable" - so I am still doing "outer.this.me" aren't I? In any case, won't the value of "self" from the "old" instance still be the "correct" ActorRef?

No, since we null it out to reduce the impact of memory leaks (i.e. if your code were to leak a reference to the actor instance, we at least sever the normal ties to the actor system). And unfortunately every closure you generate within a class—including by-name args—will currently capture a reference to its enclosing scope (recursively). See ticket SI-1419 in the scala tracker. 

Regards,

Roland Kuhn
Typesafe — The software stack for applications that scale
twitter: @rolandkuhn

oxbow_lakes

unread,
May 25, 2012, 1:10:50 PM5/25/12
to akka...@googlegroups.com
Sorry, I'm still none the wiser. I understand the point about me accessing self via "this" (which may be an "old" instance), but it seems to me that the actual ActorRef which will be returned is still valid and I should be able to send messages to it (and they will be processed by the "correct" instance). So I guess that is the question: is an ActorRef always valid, assuming that the actor it represents is still running, even if it was obtained via an instance which is longer represents the current state of the actor.

Is there official Akka terminology for "the instance which will be called when an ActorRef receives a message"?

C

oxbow_lakes

unread,
May 25, 2012, 1:12:34 PM5/25/12
to akka...@googlegroups.com
but self is a "final val" - how do you null it out?

Roland Kuhn

unread,
May 25, 2012, 1:30:32 PM5/25/12
to akka...@googlegroups.com, akka...@googlegroups.com
well, using reflection of course. There is no such thing as "final" in the JVM trenches. This is why we recommend to capture by-value, and currently the only mechanism for that in Scala is to capture a local val. 



Regards,

Roland Kuhn
Typesafe — The software stack for applications that scale
twitter: @rolandkuhn
--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/ziGouHsc8dkJ.

To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.

oxbow_lakes

unread,
May 26, 2012, 5:59:31 AM5/26/12
to akka...@googlegroups.com
Do you think it's a good idea to use reflection to circumvent the language in this way? I almost didn't bother sending my original message because *obviously* as a final val, I'd be fine. As the akka system (in general) is going to be the only thing with a reference to the inner "instance", it hardly seems necessary anyway

Chris
To unsubscribe from this group, send email to akka-user+unsubscribe@googlegroups.com.

√iktor Ҡlang

unread,
May 26, 2012, 6:09:47 AM5/26/12
to akka...@googlegroups.com


On May 26, 2012 11:59 AM, "oxbow_lakes" <oxbow...@gmail.com> wrote:
>
> Do you think it's a good idea to use reflection to circumvent the language in this way?

Yes. See archives as to why.

Cheers,

V

>>> To unsubscribe from this group, send email to akka-user+...@googlegroups.com.


>>> For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.
>

> --
> You received this message because you are subscribed to the Google Groups "Akka User List" group.

> To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/6A335TMNMcgJ.


>
> To post to this group, send email to akka...@googlegroups.com.

> To unsubscribe from this group, send email to akka-user+...@googlegroups.com.

Peter Vlugter

unread,
May 26, 2012, 7:27:09 PM5/26/12
to akka...@googlegroups.com

On 26/05/2012, at 5:06 AM, Roland Kuhn wrote:

> On 25 maj 2012, at 18:37, oxbow_lakes <oxbow...@gmail.com> wrote:
>
>> I still don't understand the difference. In the code:
>>
>> val me = self
>> def apiCallback(e: ApiEvent) { me ! e }
>>
>> me is an "instance variable" - so I am still doing "outer.this.me" aren't I? In any case, won't the value of "self" from the "old" instance still be the "correct" ActorRef?
>>
> No, since we null it out to reduce the impact of memory leaks

It's not set to null anymore but to system.deadLetters. You won't get an NPE if you close over self, but you'll be sending messages to the dead letter queue (if the underlying actor instance changes). See:

https://github.com/akka/akka/blob/v2.0.1/akka-actor/src/main/scala/akka/actor/ActorCell.scala#L778

Peter Vlugter

unread,
May 26, 2012, 7:28:49 PM5/26/12
to akka...@googlegroups.com

On 27/05/2012, at 11:27 AM, Peter Vlugter wrote:

> It's not set to null anymore but to system.deadLetters. You won't get an NPE if you close over self, but you'll be sending messages to the dead letter queue (if the underlying actor instance changes). See:
>
> https://github.com/akka/akka/blob/v2.0.1/akka-actor/src/main/scala/akka/actor/ActorCell.scala#L778

Or in a more experimental way:

scala> import akka.actor._
import akka.actor._

scala> import scala.concurrent.ops.spawn
import scala.concurrent.ops.spawn

scala> class Test extends Actor {
| def receive = {
| case "spawn" =>
| spawn { Thread.sleep(2000); println("self = " + self) }
| throw new Exception("restart please")
| }
| }
defined class Test

scala> val system = ActorSystem("test")
system: akka.actor.ActorSystem = akka://test

scala> val test = system.actorOf(Props[Test])
test: akka.actor.ActorRef = Actor[akka://test/user/$a]

scala> test ! "spawn"

[ERROR] [05/27/2012 11:25:04.447] [test-akka.actor.default-dispatcher-3] [akka://test/user/$a] restart please
java.lang.Exception: restart please
...

self = Actor[akka://test/deadLetters]
Reply all
Reply to author
Forward
0 new messages