Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question

migrated from stackoverflow.com Mar 27 '12 at 15:56

This question came from our site for professional and enthusiast programmers.

add comment

3 Answers 3

up vote 4 down vote accepted

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.

share|improve this answer
    
Doesn't using shared state (bool passed by reference) though kinda defeat the purpose of actors? –  kahoon Mar 27 '12 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 '12 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 '12 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 '12 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 '12 at 20:23
show 1 more comment

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

share|improve this answer
    
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 '12 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 '12 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 '12 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 '12 at 20:27
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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