locked
error 2 handlers exclusively modifying states RRS feed

  • Question

  • Hi guys,

    This morning I observed a strange error while trying to have handlers modify my service state.

    So here's the situation. I have 2 simulated cameras attached on a simulated robot entity. Every 50 miliseconds, the TimerPortHandler will post 2 messages to get the cameras to take 2 pictures and store the byte[] into 2 service states

    members (of type byte[] also).

    So here's the brief code:

     

    TimerHandler:

    Code Snippet

    void TimerHandler(DateTime signal)

    {

    _mainPort.Post(new IncrementTick());

    _mainPort.Post(new GetUpdateFromJoints());

    _mainPort.Post(new GetUpdateFromLeftCamera());//first camera takes pix

    _mainPort.Post(new GetUpdateFromRightCamera());//second camera takes pix

    Activate(

    Arbiter.Receive(false, TimeoutPort(100),

    delegate(DateTime time)

    {

    _timerPort.Post(time);

    }

    )

    );

    }

     

     

    First Camera:

    Code Snippet

    [ServiceHandler(ServiceHandlerBehavior.Exclusive)]

    public IEnumerator<ITask> GetUpdateFromLeftCameraHandler(GetUpdateFromLeftCamera getUpdateFromLeftCamera)

    {

    if (rover.RobotsLeftCamera != null)

    {

    rover.RobotsLeftCamera.CaptureScene(ImageFormat.Bmp, _leftCameraPort);

    yield return Arbiter.Choice(_leftCameraPort,

    delegate(Bitmap b)

    {

    System.IO.MemoryStream stream = new System.IO.MemoryStream();

    b.Save(stream, ImageFormat.Bmp);

    byte[] byteResult = new byte[stream.Length];

    byteResult = stream.ToArray();

    stream.Close();

    _state.ByteLeft = new byte[byteResult.Length];

    _state.ByteLeft = byteResult;

    },

    delegate(Exception ex)

    {

    }

    );

    }

    getUpdateFromLeftCamera.ResponsePort.Post(DefaultUpdateResponseType.Instance);

    yield break;

    }

     

     

    Second Camera:

    Code Snippet

    [ServiceHandler(ServiceHandlerBehavior.Exclusive)]

    public IEnumerator<ITask> GetUpdateFromRightCameraHandler(GetUpdateFromRightCamera getUpdateFromRightCamera)

    {

    if (rover.RobotsRightCamera != null)

    {

    rover.RobotsRightCamera.CaptureScene(ImageFormat.Bmp, _rightCameraPort);

    yield return Arbiter.Choice(_rightCameraPort,

    delegate(Bitmap b)

    {

    System.IO.MemoryStream stream2 = new System.IO.MemoryStream();

    b.Save(stream2, ImageFormat.Bmp);

    byte[] byteResult = new byte[stream2.Length];

    byteResult = stream2.ToArray();

    stream2.Close();

    _state.ByteRight = new byte[byteResult.Length];

    _state.ByteRight = byteResult;

    },

    delegate(Exception ex)

    {

    }

    );

    }

    getUpdateFromRightCamera.ResponsePort.Post(DefaultUpdateResponseType.Instance);

    yield break;

    }

     

     

    Now, when the GetUpdateFromLeftCameraHandler and GetUpdateFromRightCameraHandler are marked "Exclusive", nothing works, like this service doesnt seem to update any of its state members at all (I have a subsriber to listen to any of these state changes).

     

    Strangely enough, when the ServiceHandlerBehaviors are marked to "Concurrent" everything works out nicely.

     

    I learned from the Service Tutorials that if a handler is trying to modify a state, it should be doing it exclusively, not concurrently. Therefore, I dont feel right with this solution.

     

    Could anyone tell me what happened there and the solution to this?

     

    Thanks guys, 

    Friday, August 3, 2007 1:54 PM

Answers

  • you can make your exclsuive handlers finish fast, or make your handlers concurrent, and have them post an Update on their own mainPort, if they need to modify state. So logic can run concurrent, but updates get serialized.

     

    our service tutorials show this pattern

    Tuesday, August 21, 2007 2:38 AM

All replies

  • Hi, first let me suggest what i would do in this case, then we can talk about the issue with exclusive:

     

    1) Exclusive will prevent your service from doing any work, and should only be used if you have *multiple* fields you are updating or have some multiple step stae machine you need ot execute without interruption. In your case, since you have twoindependent fields tracking the camera image, there is no need for exclusive.

     

    2) In your timer handler routine, you send 4 requests one after the other, but never wait for their responses. YOu then activate on the timer. There is no guarantee that the requests have finished processing by the time your timer handler executes again. If you want to concurrently take pictures, update the tick etc, you can still issue all those requests, but then use Arbiter.Join to gather their results, *then* re-issue the timer request. Or just use Activate() to attach some delegates for each response, then using an interlocked counter, etcissue the timer handler when the count of pending requests is zero.

     

    So let me know if my assumptions above are correct, and we can go from there.

     

     

    Friday, August 3, 2007 6:14 PM
  • Hi,

    Your post was an eye-opener for me George,

     

    For my program, I don't need the 4 requests to wait for each other response. I just need them to get their jobs done before the next time the Timer is activated.

    How do I use Arbiter.Join() in my case?

    Sorry but the second way you mention was pretty over my head at the moment, would you mind elaborate on that a bit too ?

     

    Thanks

     

    Saturday, August 18, 2007 5:47 PM
  • Hi, we have examples with joins and other advanced primitives in the CCR user guide, part of the MSRS runtime docs.

     

    Sunday, August 19, 2007 7:04 AM
  • Hi,

    Thanks a lot George, for your reply.

    I have another question though. My GetUpdateFromJoints above is supposed to update every 50 miliseconds or so. If a Joystick signal comes in (can be anytime, not periodic) while the GetUpdateFromJoints have not finished its job. And both the Joystick and the GetUpdateFromJoints() want to update the same state variables, then how do we resolve the conflict between the two?

    Should GetUpdateFromJoints be made Concurrent, it seems like it wouldnt solve the problem?

    I know my question sounds pretty basic. But please give me suggestion.

     

    Thanks a lot, George

     

     

     

     

    Sunday, August 19, 2007 1:17 PM
  • you can make your exclsuive handlers finish fast, or make your handlers concurrent, and have them post an Update on their own mainPort, if they need to modify state. So logic can run concurrent, but updates get serialized.

     

    our service tutorials show this pattern

    Tuesday, August 21, 2007 2:38 AM