Esempio n. 1
0
        public void DeleteTimer(TimerQueueTimer timer)
        {
            if (timer.m_dueTime != Timeout.UnsignedInfinite)
            {
                if (timer.m_next != null)
                    timer.m_next.m_prev = timer.m_prev;
                if (timer.m_prev != null)
                    timer.m_prev.m_next = timer.m_next;
                if (m_timers == timer)
                    m_timers = timer.m_next;

                timer.m_dueTime = Timeout.UnsignedInfinite;
                timer.m_period = Timeout.UnsignedInfinite;
                timer.m_startTicks = 0;
                timer.m_prev = null;
                timer.m_next = null;
            }
        }
Esempio n. 2
0
 public TimerHolder(TimerQueueTimer timer) 
 { 
     m_timer = timer; 
 }
Esempio n. 3
0
        private static void QueueTimerCompletion(TimerQueueTimer timer)
        {
            WaitCallback callback = s_fireQueuedTimerCompletion;
            if (callback == null)
                s_fireQueuedTimerCompletion = callback = new WaitCallback(FireQueuedTimerCompletion);

            // Can use "unsafe" variant because we take care of capturing and restoring
            // the ExecutionContext.
            ThreadPool.UnsafeQueueUserWorkItem(callback, timer);
        }
Esempio n. 4
0
 public bool UpdateTimer(TimerQueueTimer timer, uint dueTime, uint period)
 {
     if (timer.m_dueTime == Timeout.UnsignedInfinite)
     {
         // the timer is not in the list; add it (as the head of the list).
         timer.m_next = m_timers;
         timer.m_prev = null;
         if (timer.m_next != null)
             timer.m_next.m_prev = timer;
         m_timers = timer;
     }
     timer.m_dueTime = dueTime;
     timer.m_period = (period == 0) ? Timeout.UnsignedInfinite : period;
     timer.m_startTicks = TickCount;
     return EnsureAppDomainTimerFiresBy(dueTime);
 }
Esempio n. 5
0
        internal void Resume()
        {
            //
            // Update timers to adjust their due-time to accomodate Pause/Resume
            //
            lock (this)
            {
                // prevent ThreadAbort while updating state
                try { }
                finally
                {
                    int pauseTicks = m_pauseTicks;
                    m_pauseTicks = 0; // Set this to 0 so that now timers can be scheduled

                    int resumedTicks  = TickCount;
                    int pauseDuration = resumedTicks - pauseTicks;

                    bool haveTimerToSchedule        = false;
                    uint nextAppDomainTimerDuration = uint.MaxValue;

                    TimerQueueTimer timer = m_timers;
                    while (timer != null)
                    {
                        Contract.Assert(timer.m_dueTime != Timeout.UnsignedInfinite);
                        Contract.Assert(resumedTicks >= timer.m_startTicks);

                        uint elapsed; // How much of the timer dueTime has already elapsed

                        // Timers started before the paused event has to be sufficiently delayed to accomodate
                        // for the Pause time. However, timers started after the Paused event shouldnt be adjusted.
                        // E.g. ones created by the app in its Activated event should fire when it was designated.
                        // The Resumed event which is where this routine is executing is after this Activated and hence
                        // shouldn't delay this timer

                        if (timer.m_startTicks <= pauseTicks)
                        {
                            elapsed = (uint)(pauseTicks - timer.m_startTicks);
                        }
                        else
                        {
                            elapsed = (uint)(resumedTicks - timer.m_startTicks);
                        }

                        // Handling the corner cases where a Timer was already due by the time Resume is happening,
                        // We shouldn't delay those timers.
                        // Example is a timer started in App's Activated event with a very small duration
                        timer.m_dueTime    = (timer.m_dueTime > elapsed) ? timer.m_dueTime - elapsed : 0;;
                        timer.m_startTicks = resumedTicks; // re-baseline

                        if (timer.m_dueTime < nextAppDomainTimerDuration)
                        {
                            haveTimerToSchedule        = true;
                            nextAppDomainTimerDuration = timer.m_dueTime;
                        }

                        timer = timer.m_next;
                    }

                    if (haveTimerToSchedule)
                    {
                        EnsureAppDomainTimerFiresBy(nextAppDomainTimerDuration);
                    }
                }
            }
        }
        public bool InitModel()
        {
            //try
            //{
            //    // ***********************************************
            //    // set up generic UDP socket and bind to local port
            //    // ***********************************************
            //    _dataSocket = new UdpClient((int)_localPort);
            //}
            //catch (Exception ex)
            //{
            //    Debug.Write(ex.ToString());
            //    return false;
            //}

            // this delegate is needed for the multi media timer defined
            // in the TimerQueueTimer class.
            _ballTimerCallbackDelegate = new TimerQueueTimer.WaitOrTimerDelegate(BallMMTimerCallback);

            // create our multi-media timers
            _ballHiResTimer = new TimerQueueTimer();
            try
            {
                // create a Multi Media Hi Res timer.
                _ballHiResTimer.Create(10, 10, _ballTimerCallbackDelegate);
            }
            catch (QueueTimerException ex)
            {
                Console.WriteLine(ex.ToString());
                Console.WriteLine("Failed to create Ball timer. Error from GetLastError = {0}", ex.Error);
            }

            _paddleTimerCallbackDelegate = new TimerQueueTimer.WaitOrTimerDelegate(paddleMMTimerCallback);
            _paddleHiResTimer = new TimerQueueTimer();
            try
            {
                // create a Multi Media Hi Res timer.
                _paddleHiResTimer.Create(10, 8, _paddleTimerCallbackDelegate);
            }
            catch (QueueTimerException ex)
            {
                Console.WriteLine(ex.ToString());
                Console.WriteLine("Failed to create paddle timer. Error from GetLastError = {0}", ex.Error);
            }

            // reset help text
            //HelpText = "";
            ThreadStart threadFunction;
            threadFunction = new ThreadStart(SynchWithOtherPlayer);
            _syncWithOtherPlayerThread = new Thread(threadFunction);
            return true;
        }
Esempio n. 7
0
 public TimerHolder(TimerQueueTimer timer)
 {
     m_timer = timer;
 }
Esempio n. 8
0
 private void LinkTimer(TimerQueueTimer timer)
 {
     // Use timer._short to decide to which list to add.
     ref TimerQueueTimer?listHead = ref timer._short ? ref _shortTimers : ref _longTimers;
Esempio n. 9
0
        private static void CallCallbackInContext(object state)
        {
            TimerQueueTimer t = (TimerQueueTimer)state;

            t._timerCallback(t._state);
        }
Esempio n. 10
0
        //
        // Fire any timers that have expired, and update the native timer to schedule the rest of them.
        //
        private void FireNextTimers()
        {
            //
            // we fire the first timer on this thread; any other timers that might have fired are queued
            // to the ThreadPool.
            //
            TimerQueueTimer timerToFireOnThisThread = null;

            using (LockHolder.Hold(Lock))
            {
                //
                // since we got here, that means our previous timer has fired.
                //
                ReleaseTimer();
                _currentNativeTimerDuration = UInt32.MaxValue;

                bool haveTimerToSchedule        = false;
                uint nextAppDomainTimerDuration = uint.MaxValue;

                int nowTicks = TickCount;

                //
                // Sweep through all timers.  The ones that have reached their due time
                // will fire.  We will calculate the next native timer due time from the
                // other timers.
                //
                TimerQueueTimer timer = _timers;
                while (timer != null)
                {
                    Debug.Assert(timer.m_dueTime != Timeout.UnsignedInfinite);

                    uint elapsed = (uint)(nowTicks - timer.m_startTicks);
                    if (elapsed >= timer.m_dueTime)
                    {
                        //
                        // Remember the next timer in case we delete this one
                        //
                        TimerQueueTimer nextTimer = timer.m_next;

                        if (timer.m_period != Timeout.UnsignedInfinite)
                        {
                            timer.m_startTicks = nowTicks;
                            timer.m_dueTime    = timer.m_period;

                            //
                            // This is a repeating timer; schedule it to run again.
                            //
                            if (timer.m_dueTime < nextAppDomainTimerDuration)
                            {
                                haveTimerToSchedule        = true;
                                nextAppDomainTimerDuration = timer.m_dueTime;
                            }
                        }
                        else
                        {
                            //
                            // Not repeating; remove it from the queue
                            //
                            DeleteTimer(timer);
                        }

                        //
                        // If this is the first timer, we'll fire it on this thread.  Otherwise, queue it
                        // to the ThreadPool.
                        //
                        if (timerToFireOnThisThread == null)
                        {
                            timerToFireOnThisThread = timer;
                        }
                        else
                        {
                            QueueTimerCompletion(timer);
                        }

                        timer = nextTimer;
                    }
                    else
                    {
                        //
                        // This timer hasn't fired yet.  Just update the next time the native timer fires.
                        //
                        uint remaining = timer.m_dueTime - elapsed;
                        if (remaining < nextAppDomainTimerDuration)
                        {
                            haveTimerToSchedule        = true;
                            nextAppDomainTimerDuration = remaining;
                        }
                        timer = timer.m_next;
                    }
                }

                if (haveTimerToSchedule)
                {
                    EnsureAppDomainTimerFiresBy(nextAppDomainTimerDuration);
                }
            }

            //
            // Fire the user timer outside of the lock!
            //
            if (timerToFireOnThisThread != null)
            {
                timerToFireOnThisThread.Fire();
            }
        }
Esempio n. 11
0
        // Fire any timers that have expired, and update the native timer to schedule the rest of them.
        // We're in a thread pool work item here, and if there are multiple timers to be fired, we want
        // to queue all but the first one.  The first may can then be invoked synchronously or queued,
        // a task left up to our caller, which might be firing timers from multiple queues.
        private void FireNextTimers()
        {
            // We fire the first timer on this thread; any other timers that need to be fired
            // are queued to the ThreadPool.
            TimerQueueTimer timerToFireOnThisThread = null;

            lock (this)
            {
                // Since we got here, that means our previous appdomain timer has fired.
                m_isAppDomainTimerScheduled = false;
                bool haveTimerToSchedule        = false;
                uint nextAppDomainTimerDuration = uint.MaxValue;

                int nowTicks = TickCount;

                // Sweep through the "short" timers.  If the current tick count is greater than
                // the current threshold, also sweep through the "long" timers.  Finally, as part
                // of sweeping the long timers, move anything that'll fire within the next threshold
                // to the short list.  It's functionally ok if more timers end up in the short list
                // than is truly necessary (but not the opposite).
                TimerQueueTimer timer = m_shortTimers;
                for (int listNum = 0; listNum < 2; listNum++) // short == 0, long == 1
                {
                    while (timer != null)
                    {
                        Debug.Assert(timer.m_dueTime != Timeout.UnsignedInfinite, "A timer in the list must have a valid due time.");

                        // Save off the next timer to examine, in case our examination of this timer results
                        // in our deleting or moving it; we'll continue after with this saved next timer.
                        TimerQueueTimer next = timer.m_next;

                        uint elapsed   = (uint)(nowTicks - timer.m_startTicks);
                        int  remaining = (int)timer.m_dueTime - (int)elapsed;
                        if (remaining <= 0)
                        {
                            // Timer is ready to fire.

                            if (timer.m_period != Timeout.UnsignedInfinite)
                            {
                                // This is a repeating timer; schedule it to run again.

                                // Discount the extra amount of time that has elapsed since the previous firing time to
                                // prevent timer ticks from drifting.  If enough time has already elapsed for the timer to fire
                                // again, meaning the timer can't keep up with the short period, have it fire 1 ms from now to
                                // avoid spinning without a delay.
                                timer.m_startTicks = nowTicks;
                                uint elapsedForNextDueTime = elapsed - timer.m_dueTime;
                                timer.m_dueTime = (elapsedForNextDueTime < timer.m_period) ?
                                                  timer.m_period - elapsedForNextDueTime :
                                                  1;

                                // Update the appdomain timer if this becomes the next timer to fire.
                                if (timer.m_dueTime < nextAppDomainTimerDuration)
                                {
                                    haveTimerToSchedule        = true;
                                    nextAppDomainTimerDuration = timer.m_dueTime;
                                }

                                // Validate that the repeating timer is still on the right list.  It's likely that
                                // it started in the long list and was moved to the short list at some point, so
                                // we now want to move it back to the long list if that's where it belongs. Note that
                                // if we're currently processing the short list and move it to the long list, we may
                                // end up revisiting it again if we also enumerate the long list, but we will have already
                                // updated the due time appropriately so that we won't fire it again (it's also possible
                                // but rare that we could be moving a timer from the long list to the short list here,
                                // if the initial due time was set to be long but the timer then had a short period).
                                bool targetShortList = (nowTicks + timer.m_dueTime) - m_currentAbsoluteThreshold <= 0;
                                if (timer.m_short != targetShortList)
                                {
                                    MoveTimerToCorrectList(timer, targetShortList);
                                }
                            }
                            else
                            {
                                // Not repeating; remove it from the queue
                                DeleteTimer(timer);
                            }

                            // If this is the first timer, we'll fire it on this thread (after processing
                            // all others). Otherwise, queue it to the ThreadPool.
                            if (timerToFireOnThisThread == null)
                            {
                                timerToFireOnThisThread = timer;
                            }
                            else
                            {
                                ThreadPool.UnsafeQueueCustomWorkItem(timer, forceGlobal: true);
                            }
                        }
                        else
                        {
                            // This timer isn't ready to fire.  Update the next time the native timer fires if necessary,
                            // and move this timer to the short list if its remaining time is now at or under the threshold.

                            if (remaining < nextAppDomainTimerDuration)
                            {
                                haveTimerToSchedule        = true;
                                nextAppDomainTimerDuration = (uint)remaining;
                            }

                            if (!timer.m_short && remaining <= ShortTimersThresholdMilliseconds)
                            {
                                MoveTimerToCorrectList(timer, shortList: true);
                            }
                        }

                        timer = next;
                    }

                    // Switch to process the long list if necessary.
                    if (listNum == 0)
                    {
                        // Determine how much time remains between now and the current threshold.  If time remains,
                        // we can skip processing the long list.  We use > rather than >= because, although we
                        // know that if remaining == 0 no timers in the long list will need to be fired, we
                        // don't know without looking at them when we'll need to call FireNextTimers again.  We
                        // could in that case just set the next appdomain firing to 1, but we may as well just iterate the
                        // long list now; otherwise, most timers created in the interim would end up in the long
                        // list and we'd likely end up paying for another invocation of FireNextTimers that could
                        // have been delayed longer (to whatever is the current minimum in the long list).
                        int remaining = m_currentAbsoluteThreshold - nowTicks;
                        if (remaining > 0)
                        {
                            if (m_shortTimers == null && m_longTimers != null)
                            {
                                // We don't have any short timers left and we haven't examined the long list,
                                // which means we likely don't have an accurate nextAppDomainTimerDuration.
                                // But we do know that nothing in the long list will be firing before or at m_currentAbsoluteThreshold,
                                // so we can just set nextAppDomainTimerDuration to the difference between then and now.
                                nextAppDomainTimerDuration = (uint)remaining + 1;
                                haveTimerToSchedule        = true;
                            }
                            break;
                        }

                        // Switch to processing the long list.
                        timer = m_longTimers;

                        // Now that we're going to process the long list, update the current threshold.
                        m_currentAbsoluteThreshold = nowTicks + ShortTimersThresholdMilliseconds;
                    }
                }

                // If we still have scheduled timers, update the appdomain timer to ensure it fires
                // in time for the next one in line.
                if (haveTimerToSchedule)
                {
                    EnsureAppDomainTimerFiresBy(nextAppDomainTimerDuration);
                }
            }

            // Fire the user timer outside of the lock!
            timerToFireOnThisThread?.Fire();
        }
Esempio n. 12
0
        private volatile int m_pauseTicks = 0; // Time when Pause was called


        //
        // Fire any timers that have expired, and update the native timer to schedule the rest of them.
        //
        private void FireNextTimers()
        {
            //
            // we fire the first timer on this thread; any other timers that might have fired are queued
            // to the ThreadPool.
            //
            TimerQueueTimer timerToFireOnThisThread = null;

            lock (this)
            {
                // prevent ThreadAbort while updating state
                try { }
                finally
                {
                    //
                    // since we got here, that means our previous timer has fired.
                    //
                    m_isAppDomainTimerScheduled = false;
                    bool haveTimerToSchedule        = false;
                    uint nextAppDomainTimerDuration = uint.MaxValue;

                    int nowTicks = TickCount;

                    //
                    // Sweep through all timers.  The ones that have reached their due time
                    // will fire.  We will calculate the next native timer due time from the
                    // other timers.
                    //
                    TimerQueueTimer timer = m_timers;
                    while (timer != null)
                    {
                        Debug.Assert(timer.m_dueTime != Timeout.UnsignedInfinite);

                        uint elapsed = (uint)(nowTicks - timer.m_startTicks);
                        if (elapsed >= timer.m_dueTime)
                        {
                            //
                            // Remember the next timer in case we delete this one
                            //
                            TimerQueueTimer nextTimer = timer.m_next;

                            if (timer.m_period != Timeout.UnsignedInfinite)
                            {
                                timer.m_startTicks = nowTicks;
                                uint elapsedForNextDueTime = elapsed - timer.m_dueTime;
                                if (elapsedForNextDueTime < timer.m_period)
                                {
                                    // Discount the extra amount of time that has elapsed since the previous firing time to
                                    // prevent timer ticks from drifting
                                    timer.m_dueTime = timer.m_period - elapsedForNextDueTime;
                                }
                                else
                                {
                                    // Enough time has elapsed to fire the timer yet again. The timer is not able to keep up
                                    // with the short period, have it fire 1 ms from now to avoid spinning without a delay.
                                    timer.m_dueTime = 1;
                                }

                                //
                                // This is a repeating timer; schedule it to run again.
                                //
                                if (timer.m_dueTime < nextAppDomainTimerDuration)
                                {
                                    haveTimerToSchedule        = true;
                                    nextAppDomainTimerDuration = timer.m_dueTime;
                                }
                            }
                            else
                            {
                                //
                                // Not repeating; remove it from the queue
                                //
                                DeleteTimer(timer);
                            }

                            //
                            // If this is the first timer, we'll fire it on this thread.  Otherwise, queue it
                            // to the ThreadPool.
                            //
                            if (timerToFireOnThisThread == null)
                            {
                                timerToFireOnThisThread = timer;
                            }
                            else
                            {
                                QueueTimerCompletion(timer);
                            }

                            timer = nextTimer;
                        }
                        else
                        {
                            //
                            // This timer hasn't fired yet.  Just update the next time the native timer fires.
                            //
                            uint remaining = timer.m_dueTime - elapsed;
                            if (remaining < nextAppDomainTimerDuration)
                            {
                                haveTimerToSchedule        = true;
                                nextAppDomainTimerDuration = remaining;
                            }
                            timer = timer.m_next;
                        }
                    }

                    if (haveTimerToSchedule)
                    {
                        EnsureAppDomainTimerFiresBy(nextAppDomainTimerDuration);
                    }
                }
            }

            //
            // Fire the user timer outside of the lock!
            //
            if (timerToFireOnThisThread != null)
            {
                timerToFireOnThisThread.Fire();
            }
        }
Esempio n. 13
0
 private static void QueueTimerCompletion(TimerQueueTimer timer)
 {
     // Can use "unsafe" variant because we take care of capturing and restoring the ExecutionContext.
     ThreadPool.UnsafeQueueCustomWorkItem(timer, forceGlobal: true);
 }