Ejemplo n.º 1
0
        /// <summary>
        /// Ensure that messages in the low priority sending queue are sent in a timely manner, but in a way such that they do not interfere with
        /// high priority messages.
        /// </summary>
        private void SendThread()
        {
            while (!m_Disposed)
            {
                //Thread.Sleep(25); //Uncomment to simulate a really slow network.
                using (Synchronizer.Cookie cookie = Synchronizer.Lock(m_SendQueue)) {
                    //find out if it is currently safe to send
                    if (m_PendingOutboundMessageCount < m_MaxConcurrentSends)
                    {
                        SendParameters nextSendItem = null;
                        using (Synchronizer.Lock(m_SendingParticipants)) {
                            nextSendItem = (SendParameters)m_SendQueue.Dequeue(m_SendingParticipants, m_CurrentSlideID);
                        }

                        if (nextSendItem != null)
                        {
                            //Trace.WriteLine("SendNow: sequence=" + nextSendItem.MessageSequence.ToString());
                            //Trace.WriteLine("SendNow: CurrentSlide=" + m_CurrentSlideID.ToString() +
                            //    ";msg slide guid=" + nextSendItem.Tags.SlideID.ToString() +
                            //    ";IsPublicNode=" + nextSendItem.IsPublicNode.ToString(), "");
                            SendNow(nextSendItem);
                            continue;
                        }
                    }

                    // If nothing can be sent, wait for the queue's status to change.
                    // This happens either when new items are inserted or m_PendingOutboundMessageCount is updated.
                    cookie.Wait();
                }
            }
        }
Ejemplo n.º 2
0
        protected void FlusherThread()
        {
            using (Synchronizer.Cookie cookie = Synchronizer.Lock(this.m_Lock)) {
                for (int refresh = 0;;)
                {
                    try {
                        if (this.m_Disposed)
                        {
                            return;
                        }

                        // Wait a random amount of time (a different period each time).
                        cookie.Wait(this.m_Random.Next(this.m_MaxRandomWait));

                        if (this.m_Disposed)
                        {
                            return;
                        }

                        foreach (Sets sets in this.m_Sets.Values)
                        {
                            // Send an RtpNackMessage containing the current nack set (if not empty).
                            if (sets.Current != null)
                            {
                                this.m_Sender.SendNack(new RtpNackMessage(sets.SSRC, sets.Current));
                                sets.Flush();
                            }
                        }

                        // After a certain amount of time, copy the entire reference set
                        // to the nack set.  However, do this *after* flushing, so we wait
                        // a little while to see if other clients will send the same NACK.
                        if (++refresh > REFRESH_SCALE)
                        {
                            refresh = 0;
                            foreach (Sets sets in this.m_Sets.Values)
                            {
                                sets.Refresh();
                            }
                        }
                    } catch (Exception e) {
                        // Report the error, but do not break out of the thread.
                        // TODO: Log the error to the system event log.
                        Trace.Fail("RTPNackManager encountered an error: " + e.ToString(), e.StackTrace);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// The thread loop which executes queued events.
        /// </summary>
        /// <remarks>
        /// The loop iterates each time <c>Monitor.Pulse(this.m_Queue)</c> is called.
        /// It is expected that this will <em>only</em> happen when either <see cref="Invoker"/>s
        /// are added to the queue <em>or</em> <see cref="Dispose"/> is called.
        /// </remarks>
        private void ProcessMessages()
        {
            Synchronizer.Cookie cookie = Synchronizer.Lock(this.m_Queue);
            try {
                while (!this.m_Disposed)
                {
                    try {
                        // Wait until we have a message in the queue.
                        if (this.m_Queue.Count <= 0)
                        {
                            cookie.Wait();
                        }

                        // Halt the thread as soon as the ThreadEventQueue is disposed.
                        if (this.m_Disposed)
                        {
                            return;
                        }

                        // Monitor.Pulse is only called either when the ThreadEventQueue is disposed
                        // or when a message is added to the queue.
                        Debug.Assert(this.m_Queue.Count > 0);

                        Invoker invoker = this.m_Queue.Dequeue();

                        // Temporarily release the lock so other threads can add things to the
                        // queue while the message is processing.  This also avoids potential deadlocks.
                        cookie.Dispose();
                        try {
                            invoker.Method();
                        } finally {
                            cookie = Synchronizer.Lock(this.m_Queue);
                        }
                    }

                    catch (Exception e) {
                        // Report the error, but do not break out of the thread.
                        // TODO: Log the error to the system event log.
                        Trace.Fail("The ThreadEventQueue encountered an error: " + e.ToString(), e.StackTrace);
                    }
                }
            } finally {
                cookie.Dispose();
            }
        }
Ejemplo n.º 4
0
        private void BeaconSenderThreadStart()
        {
            while (true)
            {
                try {
                    using (Synchronizer.Cookie cookie = Synchronizer.Lock(this)) {
                        if (this.m_Disposed)
                        {
                            return;
                        }

                        // Get the time remaining before sending the next beacon.
                        TimeSpan interval  = this.BeaconInterval;
                        long     remaining = interval.Ticks;

                        // Get the current time so we can see how much time we've actually waited.
                        long start = DateTime.Now.Ticks;
                        do
                        {
                            // Wait until either the time expired, or until Monitor.Pulse(this)
                            // indicates that the BeaconService's state has changed.
                            cookie.Wait(new TimeSpan(remaining));

                            // Return immediately if we've been disposed.
                            if (this.m_Disposed)
                            {
                                return;
                            }

                            // If the interval was previously infinite,
                            // restart the timer from scratch with the new interval.
                            if (remaining < 0)
                            {
                                remaining = this.BeaconInterval.Ticks;
                                continue;
                            }

                            // Subtract the actual time elapsed while waiting
                            // (this will be less than "remaining" if we were Pulsed).
                            remaining -= (DateTime.Now.Ticks - start);

                            // In case the interval has changed, get the new interval.
                            TimeSpan replaced = this.BeaconInterval;
                            if (replaced.Ticks < 0)
                            {
                                // Special case if the new interval is infinite;
                                // otherwise the math is wrong since -1 milliseconds is a special value.
                                remaining = replaced.Ticks;
                                continue;
                            }
                            else
                            {
                                // Add or subtract the difference between the new and old intervals.
                                // If the new interval is longer, this increases the time remaining.
                                // if the new interval is shorter, this decreases the time remaining.
                                remaining += (replaced.Ticks - interval.Ticks);
                                interval   = replaced;
                            }

                            // As long as we've got more time before the next beacon, repeat.
                        } while(remaining > 0);

                        Message message = this.MakeBeaconMessage();
                        if (message != null)
                        {
                            // Ideally, the beacon message wouldn't be subject to rebroadcast if dropped.
                            // It's periodic, so subsequent beacons will replace any dropped frames.
                            // But we want beacon messages to trigger rebroadcast of *other* dropped frames.
                            // Also, the beacon messages should be processed in the same order as other
                            // messages dealing with the state of the presentation, to avoid timing issues.
                            // Therefore, beacon messages are sent with Default priority instead of RealTime.
                            this.m_Sender.Send(message, MessagePriority.Default);
                        }
                    }
                } catch (Exception e) {
                    Trace.WriteLine("BeaconService encountered an error: "
                                    + e.ToString() + "\r\n" + e.StackTrace);
                }
            }
        }