tags:

views:

862

answers:

2

Hi,

I feel a bit insecure about using actors in Scala. I have read documentation about how to do stuff..but I guess I would also need some DON'T rules in order to feel free to use them. I think I am afraid that I will use them in a wrong way and I will not even notice it.

Can you think of something, that, if applied, would result in breaking the benefits that Scala actors bring, or even erroneous results?

Thank you, Nora

+7  A: 

I know this doesn't really answer the question, but you should at least take heart in the fact that message-based concurrency is much less prone to wierd errors than shared-memory-thread-based concurrency.

I presume you have seen the actor guidelines in Programming in Scala, but for the record:

  • Actors should not block while processing a message. Where you might want to block try to arrange to get a message later instead.
  • Use react {} rather than receive {} when possible.
  • Communicate with actors only via messages.
  • Prefer immutable messages.
  • Make messages self-contained.
DigitalRoss
Hello, Thank you for your quick answer - it makes really useful points. I was thinking that also "sharing state" is something not to be done..but I don't exactly know what this means at code level - perhaps, - having as message a class C with a private field F and with a classical getter for this field (getF) - from one actor, sending an instance of C - fro the actor actor, receiving C and calling getF ? Could this mean 'sharing state'? Thank you!
eleonora
Shared state is state accessed by more than one thread. It's not as bad as shared mutable state, but it requires reasoning about coherency unless it is shared only after construction and henceforth immutable. So, sending a reference to yourself in a message would not be the smartest move, though a reference to a mutable object is worse than a reference to an immutable one.
DigitalRoss
+19  A: 
  • Avoid !? wherever possible. You will get a locked system!

  • Always send a message from an Actor-subsystem thread. If this means creating a transient Actor via the Actor.actor method then so be it:

    case ButtonClicked(src) => Actor.actor { controller ! SaveTrade(trdFld.text) }

  • Add an "any other message" handler to your actor's reactions. Otherwise it is impossible to figure out if you are sending a message to the wrong actor:

    case other => log.warning(this + " has received unexpected message " + other

  • Don't use Actor.actor for your primary actors, sublcass Actor instead. The reason for this is that it is only by subclassing that you can provide a sensible toString method. Again, debugging actors is very difficult if your logs are littered with statements like:

    12:03 [INFO] Sending RequestTrades(2009-10-12) to scala.actors.Actor$anonfun$1

  • Document the actors in your system, explicitly stating what messages they will receive and precisely how they should calculate the response. Using actors results in the conversion of a standard procedure (normally encapsulated within a method) to become logic spread across multiple actor's reactions. It is easy to get lost without good documentation.

  • Always make sure you can communicate with your actor outside of its react loop to find its state. For example, I always declare a method to be invoked via an MBean which looks like the following code snippet. It can otherwise be very difficult to tell if your actor is running, has shut down, has a large queue of messages etc.

.

def reportState = {
  val _this = this
  synchronized {
    val msg = "%s Received request to report state with %d items in mailbox".format(
                   _this, mailboxSize) 
    log.info(msg)
  }
  Actor.actor { _this ! ReportState }
}
  • Link your actors together and use trapExit = true - otherwise they can fail silently meaning your program is not doing what you think it is and will probably go out of memory as messages remain in the actor's mailbox.

  • I think that some other interesting choices around design-decisions to be made using actors have been highlighted here and here

oxbow_lakes
Everything your other points make sense immediately, but I'm curious about your second point of always sending messages from within an Actor thread.What is the primary motivation here, performance/clarity/something else? I don't quite follow.
Michael
I see you had suffered much writing Actor code in Scala! :-)
Daniel
*@Michael* - if you do not explicitly declare an Actor yourself, one will be created for you and bound to the `Thread` as a `ThreadLocal`. It's not at all clear to me that this approach is either logically safe or clear of memory leaks. Much simpler to explicitly declare one
oxbow_lakes