public int IndexOf(CompletionPart part) { int index = _parts.IndexOf(part); Debug.Assert(index >= 0); return(index); }
public bool HasComplete(CompletionPart part) { // completeParts is used as a flag indicating completion of other assignments // Volatile.Read is used to ensure the read is not reordered/optimized to happen // before the writes. return(_graph.HasComplete(part, _completeParts)); }
public CompletionGraphBuilder AddLast(CompletionPart part) { _parts.Add(part); if (_parts.Count >= 2) { int index = _parts.Count - 1; this.Precedes(_parts[index - 1], _parts[index]); } return(this); }
public bool HasComplete(CompletionPart part, int completeParts) { int index = _parts.IndexOf(part); Debug.Assert(index >= 0); if (index < 0) { return(false); } return(index <= completeParts); }
public bool NotePartComplete(CompletionPart part) { // passing volatile completeParts byref is ok here. // ThreadSafeFlagOperations.Set performs interlocked assignments int index = _graph.IndexOf(part); if (index <= _completeParts) { return(false); } int oldIndex = _completeParts; return(Interlocked.CompareExchange(ref _completeParts, index, oldIndex) == oldIndex); }
public void SpinWaitComplete(IEnumerable <CompletionPart> parts, CancellationToken cancellationToken) { if (!parts.Any()) { return; } int index = parts.Select(p => _graph.IndexOf(p)).Max(); if (index < 0) { return; } CompletionPart part = _graph.Parts[index]; this.SpinWaitComplete(part, cancellationToken); }
public void SpinWaitComplete(CompletionPart part, CancellationToken cancellationToken) { if (HasComplete(part)) { return; } // Don't return until we've seen all of the requested CompletionParts. This ensures all // diagnostics have been reported (not necessarily on this thread). var spinWait = new SpinWait(); while (!HasComplete(part)) { cancellationToken.ThrowIfCancellationRequested(); spinWait.SpinOnce(); } }
private void VisitNode(CompletionPart node, Stack <CompletionPart> stack, HashSet <CompletionPart> visited, ArrayBuilder <CompletionPart> result) { if (stack.Contains(node)) { var items = stack.ToList(); var startIndex = items.IndexOf(node); StringBuilder sb = new StringBuilder(); for (int i = startIndex; i < items.Count; i++) { sb.Append(" -> "); sb.Append(items[i].Name); } sb.Append(node.Name); throw new InvalidOperationException("Circular dependency in the completion graph: " + sb.ToString()); } if (!visited.Add(node)) { return; } if (!_edges.TryGetValue(node, out var sources)) { result.Add(node); return; } stack.Push(node); try { foreach (var source in sources) { VisitNode(source, stack, visited, result); } result.Add(node); } finally { stack.Pop(); } }
public CompletionGraphBuilder Precedes(CompletionPart source, CompletionPart target) { if (!_parts.Contains(source)) { throw new ArgumentException("Part is not in the completion graph.", nameof(source)); } if (!_parts.Contains(target)) { throw new ArgumentException("Part is not in the completion graph.", nameof(target)); } if (source == CompletionPart.None) { throw new ArgumentException("Part cannot depend on CompletionPart.None", nameof(source)); } if (source == CompletionPart.All) { throw new ArgumentException("Part cannot depend on CompletionPart.All", nameof(source)); } if (target == CompletionPart.None) { throw new ArgumentException("None cannot depend on another part.", nameof(target)); } if (target == CompletionPart.All) { throw new ArgumentException("All cannot depend on another part.", nameof(target)); } HashSet <CompletionPart> sources; if (!_edges.TryGetValue(target, out sources)) { sources = new HashSet <CompletionPart>(); _edges.Add(target, sources); } sources.Add(source); return(this); }
public CompletionGraphBuilder Add(CompletionPart part) { _parts.Add(part); return(this); }
public virtual bool HasComplete(CompletionPart part) { // must be overridden by source symbols, no-op for other symbols Debug.Assert(!this.RequiresCompletion); return(true); }