Interleave Iterator Handler is not firing

I've created a couple of ports whose handlers are iterators. I added them to the concurrent group of an interleave then I posted to one of the ports. The code in the handler never executes.

Code Snippet

public class myService : DsspServiceBase
{

// some code here ...

private Port<irobot.RoombaState> _bumperStatePort = new

Port<irobot.RoombaState>();
private Port<irobot.RoombaState> _wheeldropStatePort = new

Port<irobot.RoombaState>();

// some code here ...

private void OneTimeStartupMethod()
{

// some code here ...

yield return Arbiter.Interleave(
new TeardownReceiverGroup(),
new ExclusiveReceiverGroup(),
new ConcurrentReceiverGroup(
Arbiter.ReceiveWithIterator(true, _bumperStatePort,

BumperStateHandler),
Arbiter.ReceiveWithIterator(true, _wheeldropStatePort,

WheeldropStateHandler)));


_bumperStatePort.Post(_state.CreateState);

// some code here ...

}


// some code here ...


private IEnumerator<ITask> BumperStateHandler(irobot.RoombaState fullState)
{
LogInfo("Starting UpdatePowerHandler");
if (_state.CreateState == null)
{
LogError("CreateState was null in BumperStateHandler");
yield break;
}
if (fullState.Sensors.BumpsWheeldrops

!= _state.CreateState.Sensors.BumpsWheeldrops)
{
LogInfo("Identified bump or wheeldrop");
}
yield break;
}

private IEnumerator<ITask> WheeldropStateHandler(irobot.RoombaState fullState)
{
LogInfo("Starting WheeldropStateHandler");
if (_state.CreateState == null)
{
LogError("CreateState was null in WheeldropStateHandler");
yield break;
}
if (fullState.Sensors.BumpsWheeldrops

!= _state.CreateState.Sensors.BumpsWheeldrops)
{
LogInfo("Identified bump or wheeldrop");
}
yield break;
}
}

All the logs work except the ones in the handler. I must be missing a step. Any ideas?

Thanks,

Dogulas

[2365 byte] By [Dogulas] at [2008-2-16]
# 1

Ok. I had to Activate the Arbitrator.Interleave. I was confused because you don't have to activate Joins or Choice. Still don't know why, but at least I know what.

Dogulas

Dogulas at 2007-10-2 > top of Msdn Tech,Microsoft Robotics Studio,Microsoft Robotics - Concurrency and Coordination Runtime (CCR)...
# 2

Interleave can only be activated. Interleave is the only arbiter that has no "termination". So yielding to it, does nothing.

Receive, Choice, Join, MultipleReceive etc all are considered "done", when some messages are received, satisfying the constraints. Interleave on the other hand can have persisted handlers that stay alive forever. So it would never end up terminating, blocking your iterator.

Activate() is really a form of "spawn" or "execute in parallel", which is exactly what interleave needs, as a long running arbiter.

GeorgeChrysanthakopoulos at 2007-10-2 > top of Msdn Tech,Microsoft Robotics Studio,Microsoft Robotics - Concurrency and Coordination Runtime (CCR)...
# 3

Thanks George! That makes sense.

Dogulas at 2007-10-2 > top of Msdn Tech,Microsoft Robotics Studio,Microsoft Robotics - Concurrency and Coordination Runtime (CCR)...
# 4

Hi George,

Your post says:

George Chrysanthakopoulos wrote:

..........Interleave on the other hand can have persisted handlers that stay alive forever. So it would never end up terminating, blocking your iterator.

And the user guide says:

Important: Never yield to persisted receivers within an iterator. In the yield statement above, Arbiter.Receive is called with persist = false (the first argument). If the receiver is persisted, the yield is never considered satisfied, so the iterator will never progress to the next statement after the yield

Well, yesterday I yielded (by mistake) a persisted receiver and the statment after the yield was reached.

Try this:

class Program

{

static void Main(string[] args)

{

Dispatcher dispatcher = new Dispatcher(0, "Yield Test");

DispatcherQueue dq = new DispatcherQueue("Yield Test Queue");

intPort = new Port<int>();

for (int i = 0; i < 5; i++)

{

intPort.Post(i);

}

Arbiter.Activate(dq,Arbiter.FromIteratorHandler(ErroneusPersistentYield));

Console.ReadLine();

}

private static Port<int> intPort;

private static IEnumerator<ITask> ErroneusPersistentYield()

{

yield return Arbiter.Receive<int>(true,intPort, delegate(int i) {Console.WriteLine(i.ToString());});

Console.WriteLine("After yield reached");

}

}

My pc output is:

0

1

After yield reached

2

3

4

I debugged and the yield ends when the first task is completed (the persisted reciever continues its work, of course). Yield a persisted receiver is useless, but the iterator progress to the next statment after the yield (at least my computer progress to the next statment).

SERware at 2007-10-2 > top of Msdn Tech,Microsoft Robotics Studio,Microsoft Robotics - Concurrency and Coordination Runtime (CCR)...
# 5

like the user guide says, dont yield to persisted receivers ( i understand you did by accident, but i need to emphasize the point). The ccr will indeed currently let the iterator progress AND keep the receiver active since i decided that was a better semantic than locking the iterator. in future versions an exception might be thrown, so once again i strongly recommend you dont rely on this behavior.

thanx

g

GeorgeChrysanthakopoulos at 2007-10-2 > top of Msdn Tech,Microsoft Robotics Studio,Microsoft Robotics - Concurrency and Coordination Runtime (CCR)...
# 6

As far as I know, throwing a exception is the best semantic in this case.

Thanks

PD. It was a copypaste accident.

SERware at 2007-10-2 > top of Msdn Tech,Microsoft Robotics Studio,Microsoft Robotics - Concurrency and Coordination Runtime (CCR)...

Microsoft Robotics Studio

Site Classified