Пример #1
0
        internal void TryMatch(AsyncMessage newMessage)
        {
            Chord       matchedChord;
            SyncMessage primaryMessage = null;

            lock (lookupLock) {
                newMessage.AsyncMethod.Enqueue(newMessage);
                matchedChord = AsyncLookup(newMessage, ref primaryMessage);
            }
            if (matchedChord == null)
            {
                return;
            }
            if (matchedChord is SyncChord)
            {
                primaryMessage.WakeUp();
            }
            else
            {
                (matchedChord as AsyncChord).ExecuteBody(newMessage.Arguments);
            }
        }
Пример #2
0
 private Chord AsyncLookup(AsyncMessage newMessage, ref SyncMessage primaryMessage)
 {
     //we are inside a lookupLock
     foreach (Chord chord in asyncMethodToChords[newMessage.AsyncMethod])
     {
         if (chord.Match())
         {
             chord.Dequeue(ref primaryMessage, newMessage);
             if (chord is SyncChord)
             {
                 //put some contextual info in the primary message
                 primaryMessage.IsPrimary     = true;
                 primaryMessage.MatchingChord = chord as SyncChord;
                 return(chord);
             }
             else
             {
                 (chord as AsyncChord).ExecuteBody(newMessage.CollatedArguments.ToArray());
             }
         }
     }
     return(null);
 }
Пример #3
0
 internal abstract void Dequeue(ref SyncMessage primaryMessage, Message newMessage);
Пример #4
0
        /// <summary>
        /// Having receveived a sync message we will try to find a match.
        ///
        /// If a match has been found and the message isn't the primary one we wait until we get a ReturnTo call
        ///
        /// If no match has been found we wait until we are wakened up. It will be either because we are the
        /// primary message or because we will have received a ReturnTo call.
        ///
        /// This is only relevant for sync messages as async ones cannot wait.
        ///
        /// </summary>
        internal object TryMatchAndWait(SyncMessage newMessage, out object[] arguments)
        {
            arguments = null;
            bool        matchFound;
            SyncMessage primaryMessage;

            lock (lookupLock) {
                //TODO: the original version says not to queue this message... can't remember why...
                //if the arrival of this message triggers a match it will be dequeued anyway
                newMessage.SyncMethod.Enqueue(newMessage);

                matchFound = SyncLookup(out primaryMessage, newMessage);

                //TODO: would it be easier to have two lists of sync chords, one for single sync chords and another one for multiple ones?
            }
            //we can now leave our lock as the match and the dequeuing have been done

            if (matchFound)
            {
                // this message completes a chord
                // is newMessage the primary message?
                if (!newMessage.IsPrimary)
                {
                    // newMessage is an returned to non-primary message
                    // lets wake up the primary thread to tell it to do its job :)
                    primaryMessage.WakeUp();

                    //TODO: non primary methods which return void don't have to return via a Return call
                    //TODO: if no Return is called when required we must throw an exception.
                    // and wait until we get a return call
                    //TODO: do we want to timeout here???
                    newMessage.Wait();
                    //TODO: should we return now or when the main body has returned????
                    arguments = primaryMessage.OutArguments;
                    return(newMessage.ReturnValue);
                }
                //here match found and we are primary
            }
            else
            {
                // if we have no match we must wait...
                // until someone signals a match (if we are primary) or until we time out
                bool timedOut = newMessage.WaitWithTimeout();
                if (timedOut)
                {
                    //there can be a gap between the timeout and a successful match
                    //we will catch this here
                    lock (lookupLock) {
                        if (!newMessage.IsAwake)
                        {
                            //no match happened in between
                            //remove this message from the queue
                            newMessage.RemoveFromQueue();
                            //execute the code expected to be executed
                            //TODO: deal with exceptions
                            //TODO; could throw a timeout exception here... well, the action could do that...
                            return(newMessage.OnTimeOut());
                        }
                    }
                }
                // here we have been wakened up either because newMessage is primary
                // or because newMessage is non-primary and got a return call
                //TODO: deal with error of non primary not being wakened up by a return call
            }

            //got a match, find out whether we are the primary message or not.
            if (newMessage.IsPrimary)
            {
                // newMessage is an awakened or not primary message
                // tell all the other messages of this chord that this is the primary thread:
                newMessage.RegisterMessages(newMessage);
                var    args        = newMessage.CollatedArguments.ToArray();
                object returnValue = newMessage.MatchingChord.ExecuteBody(args);
                //check that all the return to have been called...
                newMessage.OutArguments = args;
                newMessage.CleanUpReturnCalls(args);

                newMessage.UnregisterMessages();
                arguments = args;
                return(returnValue);
            }
            else
            {
                // newMessage is returned to non-primary message
                arguments = newMessage.PrimaryMessage.OutArguments;
                return(newMessage.ReturnValue);
            }
        }
Пример #5
0
 internal abstract void Dequeue(int count, SyncMessage primaryMessage);
Пример #6
0
 internal void Enqueue(SyncMessage syncMessage)
 {
     lock (queueLock) {
         messageQueue.Add(syncMessage);
     }
 }
Пример #7
0
 internal override void Dequeue(int count, SyncMessage primaryMessage)
 {
     Dequeue(count, primaryMessage.CollatedArguments);
 }