using System; using System.Collections.Generic; using System.Linq; using System.Diagnostics; using glue.Extensions.String; using glue.Debugging; namespace agree { #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sealed public class TrackingTray : Tray { public TrackingTray(int tix, TypeMgr tm, int next_mark, int next_id) : base(tix, tm, next_mark, next_id) { for (int i = 0; i < Pools.Length; i++) Pools[i] = new TrackingConcurrentDictionaryConstraintPool(this, i); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public Dictionary<int, HashSet<PoolMark>> garbage_tracking = new Dictionary<int, HashSet<PoolMark>>(); public bool garbage_tracking_enable = false; public HashSet<int> stops = new HashSet<int> { 37332, 40643, 38046, 38048, 52433, 37332, 40643 }; public void StartGarbageTracking() { Action<Edge> f = null; f = (e) => { if (e.IsConstrained) { foreach (int fix in tm.GetEdgeType(e.FlagsId)._deprec_feat_indexes) { ConstraintPool cp = Pools[fix]; Edge q; if (cp.TryGetEdge(e.Mark, out q)) { //if (cp_outer.HasValue) { HashSet<PoolMark> hspm; if (!garbage_tracking.TryGetValue(q.Mark, out hspm)) garbage_tracking.Add(q.Mark, hspm = new HashSet<PoolMark>()); hspm.Add(new PoolMark(cp, e.Mark)); } f(q); } } } }; foreach (Type t in tm.type_dict.Values) { f(t.Definition.Edge); if (t.m_flags.HasFlag(Type.Flags.Expanded) && t.Expanded.Edge != t.Definition.Edge) f(t.Expanded.Edge); } Debug.WriteLine("enabling garbage tracking"); garbage_tracking_enable = true; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public class TrackingConcurrentDictionaryConstraintPool : ConcurrentTray.ConcurrentDictionaryConstraintPool { TrackingTray ctr; public TrackingConcurrentDictionaryConstraintPool(TrackingTray tr, int i_feat) : base(tr, i_feat) { this.ctr = tr; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Store the constraint for the specified mark. Handle Edge value semantics properly. /// Allows detached mark to be set for bare or atomic types /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override void SetEdge(Int32 in_mark, Edge e_new) { Debug.Assert(in_mark != 0 && in_mark >= tr._protect_mark); if (!ctr.garbage_tracking_enable) { base.SetEdge(in_mark, e_new); return; } HashSet<PoolMark> hspm; PoolMark pm = new PoolMark(this, in_mark); Edge e_old; if (this.TryGetEdge(in_mark, out e_old)) { if (e_old == e_new) return; if (e_old.Mark != e_new.Mark) { hspm = ctr.garbage_tracking[e_old.Mark]; if (!hspm.Contains(pm)) Debugger.Break(); hspm.Remove(pm); if (hspm.Count == 0) { ctr.garbage_tracking.Remove(e_old.Mark); if (e_old != default(Edge)) { Debug.WriteLine("last access for children of {0} was lost when it was switched to {1} in PoolMark {2}-{3}", e_old, e_new, this.Feature.ToUpper(), in_mark); Debug.Write("\t" + new StackTrace(true).GetFrames()[3]); } } } } ////////////////////////////////////////////////////////////////////////////// if (e_new == default(Edge)) { base.RemoveEdge(in_mark); return; } ////////////////////////////////////////////////////////////////////////////// base.cd[in_mark] = e_new; ////////////////////////////////////////////////////////////////////////////// if (!ctr.garbage_tracking.TryGetValue(e_new.Mark, out hspm)) ctr.garbage_tracking.Add(e_new.Mark, hspm = new HashSet<PoolMark>()); hspm.Add(pm); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override void RemoveEdge(Int32 in_mark) { if (!ctr.garbage_tracking_enable) { base.RemoveEdge(in_mark); return; } Edge e_old; if (this.TryGetEdge(in_mark, out e_old)) { PoolMark pm = new PoolMark(this, in_mark); HashSet<PoolMark> hspm = ctr.garbage_tracking[e_old.Mark]; if (!hspm.Contains(pm)) Debugger.Break(); hspm.Remove(pm); if (hspm.Count == 0) ctr.garbage_tracking.Remove(e_old.Mark); #if true if (hspm.Count == 0) { if (ctr.stops.Contains(in_mark)) { Debug.WriteLine("last access for children of {0} was lost when it was removed from PoolMark {1}-{2}", e_old, this.Feature.ToUpper(), in_mark); //Debug.WriteLine("\t immediate children: " + e_old.ConstrainedRefsOnly().Select(cr => cr.ToString()).StringJoin(" ")); Debug.Write("\t" + new StackTrace(true).GetFrames()[2]); } } #endif base.RemoveEdge(in_mark); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override bool TryRemoveEdge(int in_mark, out Edge e) { return cd.TryRemove(in_mark, out e); } }; #endif }