using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Linq; using miew.Tokenization; using miew.Debugging; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// base class for (also nested) Derived and Completed passive chart edges. This associaties a TFS with the parsing /// activities coordinated by a ParseControl instance /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public abstract partial class PassiveEdge : ArrayTfs, IParseObj { public PassiveEdge(ParseControl ctrl, Span sp, Entry license, Tfs tfs) : base(tfs) { this.ctrl = ctrl; this.span = sp; this.license = license; } public ParseControl ctrl; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// ITokenSpan, ICharacterSpan /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Span span; public Span TokenSpan { get { return span; } } public Span CharacterSpan { get { throw new NotImplementedException(); } } public String Text { get { return ctrl.ts_input.Source.MinimalSpanText(span); } } public bool IsEntireSpan { get { return TokenSpan.Equals(ctrl.chart.EntireSpan); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// IParseObj /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Entry license; List<IParseObj> packed_edges; public Entry License { get { return license; } } public Tfs Tfs { get { return this; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public abstract IList<IDerivation> Derivations { get; } public int deleted = 0; public IParseObj m_next; public IParseObj Next { get { return m_next; } } public bool TrySetTail(IParseObj po) { return Interlocked.CompareExchange(ref m_next, po, null) == null; } public bool TrySetNext(IParseObj po_to_set, IParseObj po_expected) { return Interlocked.CompareExchange(ref m_next, po_to_set, po_expected) == po_expected; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public void HoistPackingFrom(PassiveEdge pe_old) { var _old = pe_old.packed_edges; if (_old != null) { pe_old.packed_edges = null; if (packed_edges == null) packed_edges = _old; else packed_edges.AddRange(_old); #if false PassiveEdge[] defer = null; int _tmp, c = 0; foreach (PassiveEdge hoist in _old) { if ((_tmp = hoist.TryTransact()) == SequenceControl.ACTIVE) hoist.s_state = SequenceControl.HOLD; else if ((_tmp & SequenceControl.stb_Blocked) > 0) (defer = defer ?? new PassiveEdge[_old.Count])[c++] = hoist; } if (defer != null) { Console.WriteLine("yabba"); Environment.Exit(0); int i = -1, rem = c; do { do if (++i == c) i = 0; while (defer[i] == null); if ((_tmp = defer[i].TryTransact()) == SequenceControl.ACTIVE) defer[i].SetStateRaw(SequenceControl.HOLD); else if ((_tmp & SequenceControl.stb_Blocked) > 0) continue; defer[i] = null; } while (--rem > 0); } #else foreach (PassiveEdge hoist in _old) if (hoist.BeginTransact()) hoist.s_state = SequenceControl.HOLD; #endif } else { if (packed_edges == null) packed_edges = new List<IParseObj>(12); } packed_edges.Add(pe_old); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected IEnumerable<IDerivation> _peer_packed() { Debug.Assert(ctrl.f_parse_phase_complete); Debug.Assert(this.IsActive()); /// ok because parse phase should be complete #if false if (packed_edges != null) foreach (IParseObj parseobj in packed_edges) { if (parseobj.IsRemove()) continue; #if DEBUG var pt = parseobj as PassiveEdge; if (pt != null && pt.packed_edges != null) throw new Exception(); #endif foreach (IDerivation tree in parseobj.Derivations) yield return tree; } #else return packed_edges == null ? Derived.NoDerivations : packed_edges.Where(ce => !ce.IsRemove()).SelectMany(ce => ce.Derivations); #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// IAtomicallySequenceable /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int i_seq; public int SequenceId { get { return i_seq; } } public void SetSequenceId(int id) { i_seq = id; } int s_state; public int State { get { return s_state; } } public void SetStateRaw(int s) { s_state = s; } public bool BeginTransact() { if ((s_state & (SequenceControl.stb_Hold | SequenceControl.stb_Remove)) > 0) return false; SpinWait sw = new SpinWait(); while (true) { int q = Interlocked.CompareExchange(ref s_state, SequenceControl.TRANSACT, SequenceControl.ACTIVE); if (q == SequenceControl.ACTIVE) return true; if ((q & (SequenceControl.stb_Hold | SequenceControl.stb_Remove)) > 0) return false; sw.SpinOnce(); //Thread.Yield(); } } /// <summary> /// returns: /// 'SequenceControl.ACTIVE' if the transaction is started /// </summary> /// <returns></returns> public int TryTransact() { int _tmp = s_state; if ((_tmp & (SequenceControl.stb_Hold | SequenceControl.stb_Remove)) > 0) return _tmp; return Interlocked.CompareExchange(ref s_state, SequenceControl.TRANSACT, SequenceControl.ACTIVE); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// ISysObj /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public new ISysObj SysObjParent { get { return ctrl; } } }; }