public Task WaitForCompleteAsync(AnalysisPriority priority = AnalysisPriority.None) { var task = new WaitAnalyzableTask(); Enqueue(task, priority); return(task.Task); }
/// <summary> /// Queues the specified work to run in analysis queue. /// Exceptions are rethrown to the caller and don't affect queue processing loop. /// </summary> /// <param name="function">The work to execute</param> /// <param name="priority"></param> /// <returns></returns> public Task ExecuteInQueueAsync(Func <CancellationToken, Task> function, AnalysisPriority priority) { // If we are inside the queue already, simply call the function if (Current == this) { return(function(_ppc.CancellationToken)); } var item = new ExecuteInQueueAsyncItem <bool>(function); Enqueue(item, item.Handler, priority); return(item.Task); }
public void Enqueue(IAnalyzable item, AnalysisPriority priority) { ThrowIfDisposed(); var iPri = (int)priority; if (iPri < 0 || iPri > _queue.Length) { throw new ArgumentException("priority"); } lock (_queueLock) { // see if we have the item in the queue anywhere... for (var i = 0; i < _queue.Length; i++) { if (_queue[i].Remove(item)) { Interlocked.Decrement(ref _analysisPending); var oldPri = (AnalysisPriority)i; if (oldPri > priority) { // if it was at a higher priority then our current // priority go ahead and raise the new entry to our // old priority priority = oldPri; } break; } } // enqueue the work item Interlocked.Increment(ref _analysisPending); if (priority == AnalysisPriority.High) { // always try and process high pri items immediately _queue[iPri].Insert(0, item); } else { _queue[iPri].Add(item); } try { _workEvent.Set(); } catch (IOException) { } catch (ObjectDisposedException) { // Queue was closed while we were running } } }
private IAnalyzable GetNextItem(out AnalysisPriority priority) { for (int i = PriorityCount - 1; i >= 0; i--) { if (_queue[i].Count > 0) { var res = _queue[i][0]; _queue[i].RemoveAt(0); priority = (AnalysisPriority)i; return(res); } } priority = AnalysisPriority.None; return(null); }
private IAnalyzable GetNextItem(out AnalysisPriority priority) { for (var i = PriorityCount - 1; i >= 0; i--) { if (_queue[i].Count > 0) { var res = _queue[i][0]; _queue[i].RemoveAt(0); Interlocked.Decrement(ref _analysisPending); priority = (AnalysisPriority)i; return(res); } } priority = AnalysisPriority.None; return(null); }
private async Task HandleAnalyzable(IAnalyzable item, AnalysisPriority priority, CancellationToken cancellationToken) { if (item is IGroupableAnalysisProjectEntry groupable) { var added = _enqueuedGroups.Add(groupable.AnalysisGroup); if (added) { Enqueue(new GroupAnalysis(groupable.AnalysisGroup, this), priority); } groupable.Analyze(cancellationToken, true); } else { item.Analyze(cancellationToken); } }
internal void EnqueueItem(IDocument doc, AnalysisPriority priority = AnalysisPriority.Normal, bool enqueueForAnalysis = true) { ThrowIfDisposed(); var pending = _pendingAnalysisEnqueue.Incremented(); try { Task <IAnalysisCookie> cookieTask; using (GetDocumentParseCounter(doc, out var count)) { if (count > 3) { // Rough check to prevent unbounded queueing. If we have // multiple parses in queue, we will get the latest doc // version in one of the ones to come. return; } TraceMessage($"Parsing document {doc.DocumentUri}"); cookieTask = _parseQueue.Enqueue(doc, Analyzer.LanguageVersion); } if (doc is ProjectEntry entry) { entry.ResetCompleteAnalysis(); } AnalysisQueued(doc.DocumentUri); // The call must be fire and forget, but should not be yielding. // It is called from DidChangeTextDocument which must fully finish // since otherwise Complete() may come before the change is enqueued // for processing and the completion list will be driven off the stale data. var p = pending; cookieTask.ContinueWith(t => { if (t.IsFaulted) { // Happens when file got deleted before processing p.Dispose(); LogMessage(MessageType.Error, t.Exception.Message); return; } OnDocumentChangeProcessingComplete(doc, t.Result as VersionCookie, enqueueForAnalysis, priority, p); }).DoNotWait(); pending = null; } finally { pending?.Dispose(); } }
public void Enqueue(TAnalyzedType item, AnalysisPriority priority) { int iPri = (int)priority; if (iPri < 0 || iPri > _queue.Length) { throw new ArgumentException("priority"); } lock (_queueLock) { // see if we have the item in the queue anywhere... for (int i = 0; i < _queue.Length; i++) { if (_queue[i].Remove(item)) { AnalysisPriority oldPri = (AnalysisPriority)i; if (oldPri > priority) { // if it was at a higher priority then our current // priority go ahead and raise the new entry to our // old priority priority = oldPri; } break; } } // enqueue the work item if (priority == AnalysisPriority.High) { // always try and process high pri items immediately _queue[iPri].Insert(0, item); } else { _queue[iPri].Add(item); } _event.Set(); } }
public void Enqueue(IAnalyzable item, AnalysisPriority priority) { int iPri = (int)priority; if (iPri < 0 || iPri > _queue.Length) { throw new ArgumentException("priority"); } lock (_queueLock) { // see if we have the item in the queue anywhere... for (int i = 0; i < _queue.Length; i++) { if (_queue[i].Remove(item)) { Interlocked.Decrement(ref _analysisPending); AnalysisPriority oldPri = (AnalysisPriority)i; if (oldPri > priority) { // if it was at a higher priority then our current // priority go ahead and raise the new entry to our // old priority priority = oldPri; } break; } } // enqueue the work item Interlocked.Increment(ref _analysisPending); if (priority == AnalysisPriority.High) { // always try and process high pri items immediately _queue[iPri].Insert(0, item); } else { _queue[iPri].Add(item); } try { _workEvent.Set(); } catch (ObjectDisposedException) { // Queue was closed while we were running } } }
private async Task HandleAnalyzable(IAnalyzable item, AnalysisPriority priority, CancellationToken cancellationToken) { if (item is IGroupableAnalysisProjectEntry groupable) { var added = _enqueuedGroups.Add(groupable.AnalysisGroup); if (added) { try { Enqueue(new GroupAnalysis(groupable.AnalysisGroup, this), priority); } catch (ObjectDisposedException) when(_ppc.IsDisposed) { return; } } groupable.Analyze(cancellationToken, true); } else { item.Analyze(cancellationToken); } }
private IAnalyzable GetNextItem(out AnalysisPriority priority) { for (int i = PriorityCount - 1; i >= 0; i--) { if (_queue[i].Count > 0) { var res = _queue[i][0]; _queue[i].RemoveAt(0); Interlocked.Decrement(ref _analysisPending); priority = (AnalysisPriority)i; return res; } } priority = AnalysisPriority.None; return null; }
private void Enqueue(object key, Func <CancellationToken, Task> handler, AnalysisPriority priority) => _ppc.Produce(new QueueItem(key, handler), (int)priority);
public void Enqueue(IAnalyzable item, AnalysisPriority priority) { Enqueue(item, ct => HandleAnalyzable(item, priority, ct), priority); }
private void OnDocumentChangeProcessingComplete(IDocument doc, VersionCookie vc, bool enqueueForAnalysis, AnalysisPriority priority, IDisposable disposeWhenEnqueued) { try { if (vc != null) { foreach (var kv in vc.GetAllParts(doc.DocumentUri)) { ParseComplete(kv.Key, kv.Value.Version); } } else { ParseComplete(doc.DocumentUri, 0); } if (doc is IAnalyzable analyzable && enqueueForAnalysis) { TraceMessage($"Enqueing document {doc.DocumentUri} for analysis"); _queue.Enqueue(analyzable, priority); } disposeWhenEnqueued?.Dispose(); disposeWhenEnqueued = null; var openedFile = _openFiles.GetDocument(doc.DocumentUri); if (vc != null) { var reported = openedFile.LastReportedDiagnostics; lock (reported) { foreach (var kv in vc.GetAllParts(doc.DocumentUri)) { var part = _projectFiles.GetPart(kv.Key); if (!reported.TryGetValue(part, out var lastVersion) || lastVersion.Version < kv.Value.Version) { reported[part] = kv.Value; PublishDiagnostics(new PublishDiagnosticsEventArgs { uri = kv.Key, diagnostics = kv.Value.Diagnostics, _version = kv.Value.Version }); } } } } } catch (BadSourceException) { } catch (OperationCanceledException ex) { LogMessage(MessageType.Warning, $"Parsing {doc.DocumentUri} cancelled"); TraceMessage($"{ex}"); } catch (Exception ex) { LogMessage(MessageType.Error, ex.ToString()); } finally { disposeWhenEnqueued?.Dispose(); } }
private void OnDocumentChangeProcessingComplete(IDocument doc, VersionCookie vc, bool enqueueForAnalysis, AnalysisPriority priority, IDisposable disposeWhenEnqueued) { ThrowIfDisposed(); try { if (vc != null) { foreach (var kv in vc.GetAllParts(doc.DocumentUri)) { ParseComplete(kv.Key, kv.Value.Version); } } else { ParseComplete(doc.DocumentUri, 0); } if (doc is IAnalyzable analyzable && enqueueForAnalysis) { TraceMessage($"Enqueing document {doc.DocumentUri} for analysis"); _queue.Enqueue(analyzable, priority); } disposeWhenEnqueued?.Dispose(); disposeWhenEnqueued = null; if (vc != null) { _editorFiles.GetDocument(doc.DocumentUri).UpdateParseDiagnostics(vc, doc.DocumentUri); } } catch (BadSourceException) { } catch (OperationCanceledException ex) { LogMessage(MessageType.Warning, $"Parsing {doc.DocumentUri} cancelled"); TraceMessage($"{ex}"); } catch (Exception ex) { LogMessage(MessageType.Error, ex.ToString()); } finally { disposeWhenEnqueued?.Dispose(); } }