Ejemplo n.º 1
0
        /// <summary>
        /// This method is used to post calls to the parent engine by the Localnode class
        /// </summary>
        internal void PostMessageToParent(LocalCallDescriptor callDescriptor, bool waitForCompletion)
        {
            nodeCommandQueue.Enqueue(callDescriptor);

            try
            {
                if (waitForCompletion)
                {
                    // We should not be on the running on the callback writer thread
                    ErrorUtilities.VerifyThrow(Thread.CurrentThread != writerThread, "Should never call this function from the writer thread");

                    // We need to block until the event we posted has been processed, but if the writer thread
                    // exit due to an error the shared memory is no longer valid so there is no way to send the message
                    while (!writerThreadHasExited && nodeCommandQueue.Count > 0)
                    {
                        nodeCommandQueue.QueueEmptyEvent.WaitOne(1000, false);

                        // Check if the communication threads are supposed to exit
                        if (exitCommunicationThreads.WaitOne(0, false))
                        {
                            break;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Clear the current queue since something in the queue has caused a problem
                nodeCommandQueue.Clear();
                // Try to send the exception back to the parent
                localNode.ReportNonFatalCommunicationError(e);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Given a non-void call descriptor, calls it and retrieves the return value.
        /// </summary>
        /// <param name="callDescriptor"></param>
        /// <returns></returns>
        private object GetReplyForCallDescriptor(LocalCallDescriptor callDescriptor)
        {
            // ReplyFromParentArrived is a TLS field, so initialize it if it's empty
            if (replyFromParentArrived == null)
            {
                replyFromParentArrived = new ManualResetEvent(false);
            }

            replyFromParentArrived.Reset();
            int requestingCallNumber = callDescriptor.CallNumber;

            ReplyData replyData = new ReplyData();

            replyData.waitEvent = replyFromParentArrived;

            // Register our wait event for the call id
            lock (repliesFromParent)
            {
                repliesFromParent[requestingCallNumber] = replyData;
            }

            nodeCommandQueue.Enqueue(callDescriptor);

            replyFromParentArrived.WaitOne();

            LocalCallDescriptor reply = null;

            // Unregister the wait event
            lock (repliesFromParent)
            {
                // Get the reply
                reply = replyData.reply;
                ErrorUtilities.VerifyThrow(reply != null, "We must have a reply if the wait event was set");

                repliesFromParent.Remove(requestingCallNumber);
            }

            return(reply.GetReplyData());
        }