4

I'm reading about actor based concurrency and I appreciate the simplicity of actors sequentially processing messages on a single thread. However there is one scenario that doesn't seen possible.

Suppose that actor A sends a message to actor B, who then performs some long running task and returns a completion message to actor A. How can actor A force actor B to cancel the long running task after it has started?

If actor B is running the task in its message queue thread, it won't pick up the cancellation message until it had completed the task; if actor B runs the task in a background thread then it seems to be violating the principle of actors.

Is there a common way that this scenario is handled with actors? Or does each actor language/framework take a different approach? Or is this not a suitable problem to tackle via actors?

3 Answers 3

4

You can include in the structure of the Command a Boolean token stating whether the Command has been cancelled. Actors which enqueue this Command can retain or separately store a reference to the Command and thus to the cancellation token. During execution of the Command by a second actor, especially while waiting for long-running external processes like file or stream reading/writing, the actor should periodically check the value of this cancellation flag. To cancel the Command, any thread with knowledge of the Command can set the cancellation Boolean, and the thread running the Command will see it has been cancelled on its next inspection, stop work, clean up and exit. This generally requires the code relating to a Command to be designed with the ability to be cancelled; this doesn't necessarily require knowledge of the Command itself by the code, but it usually does require passing in a Boolean by reference, which must be periodically tested within the method.

6
  • Doesn't using shared state (bool passed by reference) though kinda defeat the purpose of actors?
    – Attila Kun
    Mar 27, 2012 at 19:01
  • It doesn't have to be shared-state messaging, but if you have Commands enqueued by some actors for work by other actors, you already have SOME shared state; the queue of actions is known by both actors.
    – KeithS
    Mar 27, 2012 at 19:29
  • @KeithS isn't the problem with your approach that you end up with mutable shared state? A queue of actions does represent state, but it should be immutable.
    – Akash
    Mar 27, 2012 at 19:37
  • @KeithS My original comment was based on the (mistaken) idea that both the sender and actor could mutate the boolean flag. As long as only the sender can mutate it then everything is safe.
    – Akash
    Mar 27, 2012 at 20:00
  • Yes, in the case of setting a flag, the flag would appear read-only to the consumer. You wouldn't want the consumer to be able to cancel itself; it should have some other means to notify its superiors of some early termination (usually due to an error).
    – KeithS
    Mar 27, 2012 at 20:23
2

Split a long-running operation into chunks and have the actor send itself a Continue-message.

4
  • Thanks, I hadn't thought of that. If we can't split the long-running operation into chunks (e.g. call to 3rd party library), are there any other choices?
    – Akash
    Mar 27, 2012 at 7:55
  • Then it's up to that 3rd party library to supply a cancelation mechanism, there's nothing for Akka to do there.
    – Viktor Klang
    Mar 27, 2012 at 10:27
  • I like the purity of this solution - nothing but messages. On the other hand, it feels slightly artificial to divide the work into chunks (maybe that is just my lack of familiarity with actors) and there may be an associated performance hit.
    – Akash
    Mar 27, 2012 at 19:56
  • I'm not sure I like this idea. If the long-running operation is atomic (indivisible, all-or-nothing), then splitting it into chunks would require some overarching "transaction control" mechanism to be able to tell the actor "we're cancelling this series of actions; return yourself and any persistent datastore you've modified to the state I told you to remember earlier". That can be harder than it sounds, especially compared to what you'd get built-in to a single method that can perform the entire atomic operation.
    – KeithS
    Mar 27, 2012 at 20:27
0

One way to do this is to to build a controller object. This controller has the ability to receive messages, and route commands to other actors. In addition, you will have another worker object where the actual processing occurs (that is the one responsible for the possibly long operation). That worker object should be able to accept commands from the controller and act on them. It can periodically check a memory location to see if it is required to continue processing or not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.