Rob Sim -- Braintech

I learned something interesting this morning that maybe is obvious to everyone here, but wasn't to me. I'm posting to make sure I have this straight.

First off, any tasks spawned by SpawnIterator from an exclusive event handler are spawned as concurrent tasks.

Second, while as far as I know no other event handler (exclusive or concurrent) can run when an exclusive handler is running, it is possible for an exclusive handler to preempt a concurrent task, which is suspended until the exclusive handler is finished. (I had assumed naively that exclusive handlers are entirely exclusive- any concurrent handlers must complete before the exclusive handler can run).

The gotcha is that if a concurrent handler is performing some long computation based on the service state, the state may change while it is running. Maybe this should be obvious, but my mental model was that if you use only observer patterns in your concurrent handlers, and update state only in exclusive handlers, then it would be safe to assume that state is immutable while a concurrent handler is running.




Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

Rob Sim -- Braintech

Correction to my second point above:
I think I understand what my problem is. I'm mistaken about the gotcha above, when it comes to *handlers managed by the interleave*. However, it appears to me that tasks spawned by SpawnIterator are not considered when the interleave dispatches an exclusive handler. Therefore, an exclusive handler can run concurrently with tasks instantiated by a SpawnIterator call. If I'm mistaken, let me know and I'll post some code.

From the Interleave documentation (bold added):
Intelreave will guarantee that the user delegates associated with the receivers in the Exclusive group will run Exclusive to eah other and any delegate associated with the Concurrent receivers. Interleav eis biased towards Exclusive receivers so if a Concurrent receiver is currently executing and an Exclusive receiver is ready to execute, it will wait untilt he Concurrent receiver is complete and it will preempt any more Concurrent receivers from running until all Exclusive receivers have run











Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

Aaron Lahman - MSFT

Are you using SpawnIterator from your message handlers Why not use yield return Arbiter.IteratorHandler( myHandler )

Arbiter.IteratorHandler doesn't support passing arguments to the handler. Howerver, if you need to pass arguments to your iterator handler, you could instead do a foreach over the iterator with yield return -- which is most of the behavior that Arbiter.IteratorHandler would get you:

Code Snippet

[ServiceHandler(ServiceHandlerBehavior.Exclusive)]

public virtual IEnumerator<ITask> ReplaceHandler(Replace replace)

{

foreach (ITask t in _foo.MyIteratorHandler(0, 0, 1))

yield return t;

// ...

}

private IEnumerator<ITask> MyIteratorHandler(int a, int b, int c)

{

// ... do stuff

yield return ...

// ... do more stuff

yield break;

}

#aaron





Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

Rob Sim -- Braintech

The SpawnIterator call was a cut-and-paste job from one of the tutorials. :-) In fact, all I really need is a simple function call.

I'd like some clarification, though, about tasks spawned from exclusive handlers. SpawnIterator produces concurrent tasks (that seem to run *even when an exclusive handler is running!*). What about delegates to Activate(Arbiter.Choice(....)) I have code that is called from a Choice in an Exclusive handler that is very clearly running concurrently with another Exclusive handler. To me this is a non-intuitive behavior- is there a mechanism for controlling the exclusive/concurrent properties of spawned tasks

Thanks,
R






Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

Aaron Lahman - MSFT

I believe the determination depends on whether you yield return vs. activate. If you use yield return, the task is considered part of your handler and takes on Concurrent or Exclusive behavior that way. As well, the task gets handled 'synchronously' like a function call -- your handler will not get control back from the 'yield return' until the task completes. Activate, on the other hand, is 'asynchronous', and I don't think it even takes part in the interleave or the handler in any way.

Try out using the 'yield return' syntax. Any task returned via yield return should work 'like a function call'. The exception being that the CCR can re-use the thread until the operation completes. Otherwise, it should be more-or-less like a blocking function call.

#aaron





Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

Rob Sim -- Braintech

Thanks, Aaron, this is very helpful. I'll give it a whirl.

Is this distinction documented anywhere It seems like one of those non-obvious but critical bits of knowledge.

cheers,
R





Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

Ben Axelrod

One more thing to note is whether or not you combine your interleave with the main port interleave. I am not 100% sure on this, but i believe that if you don't do MainPortInterleave.CombineWith(), then the handlers will only be exclusive with respect to each other, not your main port. If i am wrong on this, please let me know...

Code Snippet


// These are exclusive with respect to the _mainPort
this.MainPortInterleave.CombineWith(new Interleave(
new ExclusiveReceiverGroup(
Arbiter.Receive<Foo>(true, _somePort, SomeHandler),
Arbiter.Receive<Bar>(true, _somePort, SomeOtherHandler)
),
new ConcurrentReceiverGroup())
);

// These are only exclusive with respect to each other
Arbiter.Interleave(
new TeardownReceiverGroup(),
new ExclusiveReceiverGroup(
Arbiter.Receive<Foo2>(true, _somePort2, SomeHandler2),
Arbiter.Receive<Bar2>(true, _somePort2, SomeOtherHandler2)
),
new ConcurrentReceiverGroup()
);








Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

Aaron Lahman - MSFT

Ben,

CcrServiceBase.SpawnIterator() does not return an interleave. As far as I can tell, it doesn't take part in any interleave. The same appears to be true of CcrServiceBase.Activate(). Neither of these methods appear to be appropriate for scheduling tasks that must be synchronous with respect to the caller*.

#aaron

* again, synchronous with the calling code, blocking it from executing until the scheduled task completes. Not necessarily synchronous / blocking with respect to the underlying OS thread or CLR thread. The 'yield return' syntax allows the CLR to reuse the thread while the method body is blocked.





Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

Rob Sim -- Braintech

Hi all,

Aaron, you were right- now everything works great. :-)

The key lesson from this is that, unless your spawned tasks can run truly concurrently (even concurrent with exclusive handlers), you should avoid SpawnIterator and Activate() and instead use yield return.

Also, this leads to the problem that the simplesoccerplayer example is perhaps not the best example of how to build a thread-safe data processor that reads/writes the service state. Most of the important things it does are protected by message passing, but in one case it changes state from inside a SpawnIterator task, and if one were to augment it to read further info from the state (that can be concurrently updated by an exclusive handler), it would not be safe at all.

For image processing, using exclusive handlers raises the annoying problem that you wind up with long-running tasks that effectively block other service tasks from running. If you want to run the tasks concurrent with other handlers, you need to carefully collect all the state information you need to perform the task (presumably using message passing) and then return the result, again using a message. As much as I can appreciate the elegance of the message passing paradigm, I'm used to the more traditional model where a simple mutex can be used to guard the collection of state information, without the overhead of constructing and dispatching a message.

... just wrapping my head around this new world view. :-)

cheers,
R






Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Semantics of Concurrent vs Exclusive in interleave.

George Chrysanthakopoulos

What we are missing is a good CCR user guide which we should be able to crank out this summer. Getting back your issues, i believe they have been addressed but to summarize:

1) Exxlusive/Concurrent handlers are protected as long as you use the "yield return" syntax. This tells the interleave you are done yet with your computation. If you use Activate or Spawn, its considered a globally concurrent, independent task

2) You can actually spawn AND wait for ann entire iterator handler to complete, and at the same time get protection from the interleave. Use the new Arbiter.ExecuteToCompletion helper method, to yield return to an entire iterator. You can even pass arguments to the iterator you are starting. See thread on new Arbiters for CCR 1.5