示例#1
0
        public int IndexOf(CompletionPart part)
        {
            int index = _parts.IndexOf(part);

            Debug.Assert(index >= 0);
            return(index);
        }
示例#2
0
 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));
 }
示例#3
0
 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);
 }
示例#4
0
        public bool HasComplete(CompletionPart part, int completeParts)
        {
            int index = _parts.IndexOf(part);

            Debug.Assert(index >= 0);
            if (index < 0)
            {
                return(false);
            }
            return(index <= completeParts);
        }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        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();
            }
        }
示例#8
0
 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();
     }
 }
示例#9
0
        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);
        }
示例#10
0
 public CompletionGraphBuilder Add(CompletionPart part)
 {
     _parts.Add(part);
     return(this);
 }
示例#11
0
 public virtual bool HasComplete(CompletionPart part)
 {
     // must be overridden by source symbols, no-op for other symbols
     Debug.Assert(!this.RequiresCompletion);
     return(true);
 }