/// <summary> /// Deactivates and disables this root clock. /// </summary> internal void RootDisable() { Debug.Assert(IsTimeManager, "Invalid call to RootDeactivate for a non-root Clock"); // Reset the state of the timing tree WeakRefEnumerator <Clock> enumerator = new WeakRefEnumerator <Clock>(_rootChildren); while (enumerator.MoveNext()) { PrefixSubtreeEnumerator subtree = new PrefixSubtreeEnumerator(enumerator.Current, true); while (subtree.MoveNext()) { if (subtree.Current.InternalCurrentClockState != ClockState.Stopped) { subtree.Current.ResetCachedStateToStopped(); subtree.Current.RaiseCurrentStateInvalidated(); subtree.Current.RaiseCurrentTimeInvalidated(); subtree.Current.RaiseCurrentGlobalSpeedInvalidated(); } else { subtree.SkipSubtree(); } } } }
// Called on the root internal void ComputeTreeState() { Debug.Assert(IsTimeManager); // Revive all children WeakRefEnumerator <Clock> enumerator = new WeakRefEnumerator <Clock>(_rootChildren); while (enumerator.MoveNext()) { PrefixSubtreeEnumerator prefixEnumerator = new PrefixSubtreeEnumerator(enumerator.Current, true); while (prefixEnumerator.MoveNext()) { Clock current = prefixEnumerator.Current; // Only traverse the "ripe" subset of the Timing tree if (CurrentGlobalTime >= current.InternalNextTickNeededTime) { current.ApplyDesiredFrameRateToGlobalTime(); current.ComputeLocalState(); // Compute the state of the node current.ClipNextTickByParent(); // Perform NextTick clipping, stage 1 // Make a note to visit for stage 2, only for ClockGroups and Roots current.NeedsPostfixTraversal = (current is ClockGroup) || (current.IsRoot); } else { prefixEnumerator.SkipSubtree(); } } } // To perform a postfix walk culled by NeedsPostfixTraversal flag, we use a local recursive method // Note that since we called for this operation, it is probably already needed by the root clock ComputeTreeStateRoot(); }
// This is only to be called on the TimeManager clock. Go through our // top level clocks and find the clock with the highest desired framerate. // DFR has to be > 0, so starting the accumulator at 0 is fine. internal int GetMaxDesiredFrameRate() { Debug.Assert(IsTimeManager); int desiredFrameRate = 0; // Ask all top-level clock their desired framerate WeakRefEnumerator <Clock> enumerator = new WeakRefEnumerator <Clock>(_rootChildren); while (enumerator.MoveNext()) { Clock currentClock = enumerator.Current; if (currentClock != null && currentClock.CurrentState == ClockState.Active) { int?currentDesiredFrameRate = currentClock.DesiredFrameRate; if (currentDesiredFrameRate.HasValue) { desiredFrameRate = Math.Max(desiredFrameRate, currentDesiredFrameRate.Value); } } } return(desiredFrameRate); }
/// <summary> /// Removes dead weak references from the child list of the root clock. /// </summary> internal void RootCleanChildren() { Debug.Assert(IsTimeManager, "Invalid call to RootCleanChildren for a non-root Clock"); WeakRefEnumerator <Clock> enumerator = new WeakRefEnumerator <Clock>(_rootChildren); // Simply enumerating the children with the weak reference // enumerator is sufficient to clean up the list. Therefore, the // body of the loop can remain empty while (enumerator.MoveNext()) { } // When the loop terminates naturally the enumerator will clean // up the list of any dead references. Therefore, by the time we // get here we are done. }
internal void ComputeTreeStateRoot() { Debug.Assert(IsTimeManager); TimeSpan?previousTickNeededTime = InternalNextTickNeededTime; InternalNextTickNeededTime = null; // Reset the root's next tick needed time WeakRefEnumerator <Clock> enumerator = new WeakRefEnumerator <Clock>(_rootChildren); while (enumerator.MoveNext()) { Clock current = enumerator.Current; if (current.NeedsPostfixTraversal) { if (current is ClockGroup) { ((ClockGroup)current).ComputeTreeStatePostfix(); } current.ApplyDesiredFrameRateToNextTick(); // Apply the effects of DFR on each root as needed current.NeedsPostfixTraversal = false; // Reset the flag } if (!InternalNextTickNeededTime.HasValue || (enumerator.Current.InternalNextTickNeededTime.HasValue && enumerator.Current.InternalNextTickNeededTime < InternalNextTickNeededTime)) { InternalNextTickNeededTime = enumerator.Current.InternalNextTickNeededTime; } } if (InternalNextTickNeededTime.HasValue && (!previousTickNeededTime.HasValue || previousTickNeededTime > InternalNextTickNeededTime)) { _timeManager.NotifyNewEarliestFutureActivity(); } }