public void Set(Container self, ref TrackableObjectMixIn <Container> mixIn, T value) { try { Tracker.OpenBatch(); if (accessor.IsVariable()) { if (trackingData != null && !IsEqualToCached(value, null)) { Tracker.logger?.Log(GetName(self), $"new and different value '{value}' set and we're a variable"); EnsureKnownAsStale(self); // FIXME: to be optimized accessor.Set(self, value); trackingData.cachedValue = value; EnsureKnownAsStable(self, isModified: true); } else { accessor.Set(self, value); } } else { // We don't care about non-variable settings. accessor.Set(self, value); } } finally { Tracker.CloseBatch(); } }
public T Get(Container self, ref TrackableObjectMixIn <Container> mixIn) { if (Tracker.AreEvaluating) { Tracker.NoteEvaluation(GetOurselvesAsDependency(self)); if (trackingData == null) { trackingData = new TrackingData <T>(); trackingData.haveModifiedDependencies = true; } } if (trackingData != null) { if (NeedsUpdate) { using (Tracker.Batch()) Update(self, ref mixIn, "on value request during tracking evaluation"); } return(GetCachedValue()); } else { return(accessor.Get(self)); } }
public void Update(Container self, ref TrackableObjectMixIn <Container> mixIn, String reason) { Tracker.EvaluationRecord record; var previousValue = trackingData.cachedValue; var previousException = trackingData.cachedException; try { Tracker.OpenEvaluation(GetName(self), reason); trackingData.cachedValue = accessor.Get(self); trackingData.cachedException = null; Tracker.logger?.Log(GetName(self), $"evaluation completed with value '{trackingData.cachedValue}'"); } catch (Exception ex) { trackingData.cachedException = ex; Tracker.logger?.Log(GetName(self), $"evaluation completed with exception '{trackingData.cachedException.Message}'"); } finally { record = Tracker.CloseEvaluation(); } RectifySubscriptions(self, record.dependencies); trackingData.haveModifiedDependencies = false; }
public void Subscribe(Container self, ref TrackableObjectMixIn <Container> mixIn, Subscriber subscriber) { if (trackingData == null) { trackingData = new TrackingData <T>(); Update(self, ref mixIn, $"on alert due to subscription by {subscriber.ToString()}"); } trackingData.subscribers.Add(subscriber); }
public void Unsubscribe(Container self, ref TrackableObjectMixIn <Container> mixIn, Subscriber subscriber) { // FIXME: This has to happen out-of-line, at the end of the omb. trackingData.subscribers.Remove(subscriber); if (trackingData.subscribers.Count == 0) { Tracker.logger?.Log(GetName(self), "scheduling for relaxation"); Tracker.ScheduleForRelaxation(self, accessor.GetIndex()); } }
public void Notify(Container self, ref TrackableObjectMixIn <Container> mixIn, TrackingNotification notification) { if (trackingData == null) { throw new Exception($"Expected {nameof(trackingData)} to be non-null."); } switch (notification) { case TrackingNotification.Stale: if (trackingData.staleDependencies++ == 0) { EnsureKnownAsStale(self); } break; case TrackingNotification.ReadyUnmodified: if (--trackingData.staleDependencies == 0) { HandleDependenciesStabilized(self); EnsureKnownAsStable(self, false); } break; case TrackingNotification.ReadyModified: trackingData.haveModifiedDependencies = true; if (--trackingData.staleDependencies == 0) { HandleDependenciesStabilized(self); EnsureKnownAsStable(self, true); } break; case TrackingNotification.RelaxIfAppropriate: RelaxIfAppropriate(self); break; default: throw new Exception($"Unknown notification {notification}."); } }