none
Why Does Using The Predicate Overload with Arbiter.Receive Change the Order Tasks are processed from the Queue? RRS feed

  • Question

  • When I mentally compile and run this code I get a different result than the computer:

    classProgram
        {
            staticvoid Main(string[] args)
            {
                
                var port = newPort<object>();

                using (var taskQueue = newDispatcherQueue())
                {
                    Arbiter.Activate(taskQueue,
                        Arbiter.Interleave(
                        newTeardownReceiverGroup(),
                        newExclusiveReceiverGroup
                            (
                                Arbiter.Receive<object>(true, port, m => MessageHandler((int)m), t => t.GetType() == typeof(int)),
                                Arbiter.Receive<object>(true, port, m => MessageHandler((string)m), t => t.GetType() == typeof(string)),
                                Arbiter.Receive<object>(true, port, m => MessageHandler((double)m), t => t.GetType() == typeof(double))                            
                            ),
                        newConcurrentReceiverGroup()
                        )
                    );

                    int i = 9;
                    port.Post((double)i);                
                    port.Post(i.ToString());                
                    port.Post(i);
                    
                    Console.ReadLine();

                }

            }

            staticvoid MessageHandler(object message)
            {

                Console.WriteLine("Got Message '{0}' of type '{1}'", message.ToString(), message.GetType().ToString());
            }
            
        }

           
    I thought the output would look like this because this is the output when I don't use predicates:
    "Got Message '9' of type 'System.Double'"
    "Got Message '9' of type 'System.String'"
    "Got Message '9' of type 'System.Int32'"

    Also, the output shown above is what the result would be if the messages were truely processed in a first-in-first-out queue, right?

    So, imagine my surprise and confusion when I ran the code and the output was actually this:

    "Got Message '9' of type 'System.Int32'"
    "Got Message '9' of type 'System.String'"
    "Got Message '9' of type 'System.Double'"

    When I re-order the Arbiter.Receive's in the ExclusiveReceiverGroup I found that the order that the messages are turned into tasks and executed changed too! Specifically, the actual order the messages are processed is equal to the order of the Arbiter.Receive statements. This seems VERY strange, doesn't it?

    What am I missing here? First of all, why do the predicates alter the order in which the posted messages are handled? Secondly, why does the order of the Arbiter.Receives influence the order of the console messages?

    • Edited by Kobe1815 Friday, March 9, 2012 3:17 PM Re-worded question to be more clear an concise
    Thursday, March 8, 2012 11:44 PM

Answers

  • There is no guaranteed ordering of messages in an Interlave. Normally CCR round-robins through the ports in an Interleave which is why the messages might tend to be processed in the order they are added to the Interleave. Depending on what messages are waiting and exactly when they arrive, you can get out of order processing. Remember, an Interleave is not a single queue -- it is a collection of ports which each have individual queues.

    Trevor

    Saturday, March 10, 2012 2:15 AM