private async Task AddWriteTaskAsync <TKey>(
            MultiDictionary <TKey, Action <SqlConnection> > queue,
            TKey key, Action <SqlConnection> action,
            CancellationToken cancellationToken)
        {
            using (await _writeQueueGate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                queue.Add(key, action);

                // If we don't have an outstanding request to write the queue to the DB
                // then create one to run a short while from now.  If there is an outstanding
                // request, then it will see this write request when it runs.
                if (_flushAllTask == null)
                {
                    var token = _shutdownTokenSource.Token;
                    _flushAllTask =
                        Task.Delay(FlushAllDelayMS, token)
                        .ContinueWith(
                            async _ => await FlushAllPendingWritesAsync(token).ConfigureAwait(false),
                            token,
                            TaskContinuationOptions.None,
                            TaskScheduler.Default);
                }
            }
        }
예제 #2
0
            private async void OnConnectionChanged(object sender, bool connected)
            {
                if (connected)
                {
                    return;
                }

                // to make things simpler, this is not cancellable. I believe this
                // is okay since this handle rare cases where remote host is recycled or
                // removed
                using (await _gate.DisposableWaitAsync(CancellationToken.None).ConfigureAwait(false))
                {
                    _client.ConnectionChanged -= OnConnectionChanged;

                    _sessionDoNotAccessDirectly?.Dispose();
                    _sessionDoNotAccessDirectly = null;

                    _client = await _workspace.TryGetRemoteHostClientAsync(CancellationToken.None).ConfigureAwait(false);

                    if (_client != null)
                    {
                        // client can be null if host is shutting down
                        _client.ConnectionChanged += OnConnectionChanged;
                    }
                }
            }
예제 #3
0
 public async Task SynchronizeAssetsAsync(IEnumerable <Checksum> checksums, CancellationToken cancellationToken)
 {
     using (await s_gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
     {
         await SynchronizeAssets_NoLockAsync(checksums, cancellationToken).ConfigureAwait(false);
     }
 }
예제 #4
0
        public override async ValueTask OnDefinitionFoundAsync(DefinitionItem definition)
        {
            using (await _semaphore.DisposableWaitAsync(CancellationToken).ConfigureAwait(false))
            {
                if (_definitionToId.ContainsKey(definition))
                {
                    return;
                }

                // Assigning a new id to the definition
                _id++;
                _definitionToId.Add(definition, _id);

                // Creating a new VSReferenceItem for the definition
                var definitionItem = await GenerateVSReferenceItemAsync(
                    _id, definitionId : _id, _document, _position, definition.SourceSpans.FirstOrDefault(),
                    definition.DisplayableProperties, _metadataAsSourceFileService, definition.GetClassifiedText(),
                    definition.Tags.GetFirstGlyph(), symbolUsageInfo : null, isWrittenTo : false, CancellationToken).ConfigureAwait(false);

                if (definitionItem != null)
                {
                    // If a definition shouldn't be included in the results list if it doesn't have references, we
                    // have to hold off on reporting it until later when we do find a reference.
                    if (definition.DisplayIfNoReferences)
                    {
                        _workQueue.AddWork(definitionItem);
                    }
                    else
                    {
                        _definitionsWithoutReference.Add(definitionItem.Id, definitionItem);
                    }
                }
            }
        }
예제 #5
0
        public async Task UpdateCacheAsync(
            Uri uri,
            LSP.SemanticTokens tokens,
            CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(tokens.ResultId);

            using (await _semaphore.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                // Case 1: Document does not currently have any token sets cached. Create a cache
                // for the document and return.
                if (!_tokens.TryGetValue(uri, out var tokenSets))
                {
                    _tokens.Add(uri, new List <LSP.SemanticTokens> {
                        tokens
                    });
                    return;
                }

                // Case 2: Document already has the maximum number of token sets cached. Remove the
                // oldest token set from the cache, and then add the new token set (see case 3).
                if (tokenSets.Count >= _maxCachesPerDoc)
                {
                    tokenSets.RemoveAt(0);
                }

                // Case 3: Document has less than the maximum number of token sets cached.
                // Add new token set to cache.
                tokenSets.Add(tokens);
            }
        }
예제 #6
0
        private async Task <Solution> GetSolutionInternalAsync(
            Checksum solutionChecksum,
            bool fromPrimaryBranch,
            int workspaceVersion,
            CancellationToken cancellationToken)
        {
            var currentSolution = GetAvailableSolution(solutionChecksum);

            if (currentSolution != null)
            {
                return(currentSolution);
            }

            // make sure there is always only one that creates a new solution
            using (await s_gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                currentSolution = GetAvailableSolution(solutionChecksum);
                if (currentSolution != null)
                {
                    return(currentSolution);
                }

                var solution = await CreateSolution_NoLockAsync(
                    solutionChecksum,
                    fromPrimaryBranch,
                    workspaceVersion,
                    PrimaryWorkspace.CurrentSolution,
                    cancellationToken).ConfigureAwait(false);

                s_lastSolution = Tuple.Create(solutionChecksum, solution);

                return(solution);
            }
        }
예제 #7
0
        public async Task <Solution> GetSolutionAsync(Checksum solutionChecksum, CancellationToken cancellationToken)
        {
            var currentSolution = s_primaryWorkspace.CurrentSolution;

            var primarySolutionChecksum = await currentSolution.State.GetChecksumAsync(cancellationToken).ConfigureAwait(false);

            if (primarySolutionChecksum == solutionChecksum)
            {
                // nothing changed
                return(currentSolution);
            }

            var lastSolution = s_lastSolution;

            if (lastSolution?.Item1 == solutionChecksum)
            {
                return(lastSolution.Item2);
            }

            // make sure there is always only one that creates a new solution
            using (await s_gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                if (s_lastSolution?.Item1 == solutionChecksum)
                {
                    return(s_lastSolution.Item2);
                }

                var solution = await CreateSolution_NoLockAsync(solutionChecksum, currentSolution, cancellationToken).ConfigureAwait(false);

                s_lastSolution = Tuple.Create(solutionChecksum, solution);

                return(solution);
            }
        }
예제 #8
0
        public async Task OnCompilationEventsGeneratedAsync(ImmutableArray <CompilationEvent> compilationEvents, AnalyzerDriver driver, CancellationToken cancellationToken)
        {
            await EnsureAnalyzerActionCountsInitializedAsync(driver, cancellationToken).ConfigureAwait(false);

            using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                await OnCompilationEventsGenerated_NoLockAsync(compilationEvents, driver, cancellationToken).ConfigureAwait(false);
            }
        }
예제 #9
0
 public async Task SynchronizeAssetsAsync(IEnumerable <Checksum> checksums, CancellationToken cancellationToken)
 {
     using (await s_gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
         using (var pooledObject = SharedPools.Default <HashSet <Checksum> >().GetPooledObject())
         {
             AddIfNeeded(pooledObject.Object, checksums);
             await _assetService.SynchronizeAssetsAsync(pooledObject.Object, cancellationToken).ConfigureAwait(false);
         }
 }
예제 #10
0
        /// <summary>
        /// Ensures that <see cref="_currentAggregateProjectContext"/> is updated for the latest TargetFrameworks from the project properties
        /// and returns this value.
        /// </summary>
        private async Task <AggregateWorkspaceProjectContext> UpdateProjectContextAsync()
        {
            // Ensure that only single thread is attempting to create a project context.
            AggregateWorkspaceProjectContext previousContextToDispose = null;

            using (await _gate.DisposableWaitAsync().ConfigureAwait(false))
            {
                // Check if we have already computed the project context.
                if (_currentAggregateProjectContext != null)
                {
                    // For non-cross targeting projects, we can use the current project context.
                    // For cross-targeting projects, we need to verify that the TargetFrameworks for the current project context matches latest TargetFrameworks project property value.
                    // If not, we create a new one and dispose the current one.

                    if (!_currentAggregateProjectContext.IsCrossTargeting)
                    {
                        return(_currentAggregateProjectContext);
                    }

                    var projectProperties = await _commonServices.ActiveConfiguredProjectProperties.GetConfigurationGeneralPropertiesAsync().ConfigureAwait(false);

                    var targetFrameworks = (string)await projectProperties.TargetFrameworks.GetValueAsync().ConfigureAwait(false);

                    if (_currentAggregateProjectContext.HasMatchingTargetFrameworks(targetFrameworks))
                    {
                        return(_currentAggregateProjectContext);
                    }

                    previousContextToDispose = _currentAggregateProjectContext;
                }

                // Force refresh the CPS active project configuration (needs UI thread).
                await _commonServices.ThreadingService.SwitchToUIThread();

                await _activeProjectConfigurationRefreshService.RefreshActiveProjectConfigurationAsync().ConfigureAwait(false);

                // Create new project context.
                _currentAggregateProjectContext = await _contextProvider.Value.CreateProjectContextAsync().ConfigureAwait(false);

                // Dispose the old project context, if one exists.
                if (previousContextToDispose != null)
                {
                    await _contextProvider.Value.ReleaseProjectContextAsync(previousContextToDispose).ConfigureAwait(false);

                    foreach (var innerContext in previousContextToDispose.DisposedInnerProjectContexts)
                    {
                        foreach (var handler in Handlers)
                        {
                            await handler.Value.OnContextReleasedAsync(innerContext).ConfigureAwait(false);
                        }
                    }
                }

                return(_currentAggregateProjectContext);
            }
        }
예제 #11
0
            private async Task <Compilation> GetOrBuildDeclarationCompilationAsync(SolutionState solution, CancellationToken cancellationToken)
            {
                try
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    using (await _buildLock.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
                    {
                        var state = this.ReadState();

                        // we are already in the final stage. just return it.
                        var compilation = state.FinalCompilation.GetValue(cancellationToken);
                        if (compilation != null)
                        {
                            return(compilation);
                        }

                        compilation = state.Compilation.GetValue(cancellationToken);
                        if (compilation == null)
                        {
                            // let's see whether we have declaration only compilation
                            if (state.DeclarationOnlyCompilation != null)
                            {
                                // okay, move to full declaration state. do this so that declaration only compilation never
                                // realize symbols.
                                var declarationOnlyCompilation = state.DeclarationOnlyCompilation.Clone();
                                this.WriteState(new FullDeclarationState(declarationOnlyCompilation), solution);
                                return(declarationOnlyCompilation);
                            }

                            // We've got nothing.  Build it from scratch :(
                            return(await BuildDeclarationCompilationFromScratchAsync(solution, cancellationToken).ConfigureAwait(false));
                        }
                        else if (state is FullDeclarationState)
                        {
                            // we have full declaration, just use it.
                            return(state.Compilation.GetValue(cancellationToken));
                        }
                        else if (state is InProgressState inProgress)
                        {
                            // We have an in progress compilation.  Build off of that.
                            return(await BuildDeclarationCompilationFromInProgressAsync(solution, inProgress, compilation, cancellationToken).ConfigureAwait(false));
                        }
                        else
                        {
                            throw ExceptionUtilities.Unreachable;
                        }
                    }
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
 private JoinableTask <T> ExecuteWithinLockAsync <T>(Func <Task <T> > task)
 {
     // We need to request the lock within a joinable task to ensure that if we are blocking the UI
     // thread (i.e. when CPS is draining critical tasks on the UI thread and is waiting on this task),
     // and the lock is already held by another task requesting UI thread access, we don't reach a deadlock.
     return(JoinableFactory.RunAsync(async delegate
     {
         using (JoinableCollection.Join())
             using (await _gate.DisposableWaitAsync().ConfigureAwait(false))
             {
                 return await task().ConfigureAwait(false);
             }
     }));
 }
예제 #13
0
 public async Task <bool> HasPendingSyntaxAnalysisAsync(SyntaxTree treeOpt, CancellationToken cancellationToken)
 {
     using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
     {
         return(_lazyPendingSyntaxAnalysisTrees != null &&
                (treeOpt != null ? _lazyPendingSyntaxAnalysisTrees.ContainsKey(treeOpt) : _lazyPendingSyntaxAnalysisTrees.Count > 0));
     }
 }
예제 #14
0
        public async Task <bool> TryInvokeAsync(string targetName, IReadOnlyList <object> arguments, CancellationToken cancellationToken)
        {
            using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                var connection = await TryGetConnection_NoLockAsync(cancellationToken).ConfigureAwait(false);

                if (connection == null)
                {
                    return(false);
                }

                await connection.InvokeAsync(targetName, arguments, cancellationToken).ConfigureAwait(false);

                return(true);
            }
        }
예제 #15
0
        /// <summary>
        /// Retrieves the base folder paths for files on the client that have been retrieved from the remote host.
        /// Triggers a refresh of all open files so we make sure they are in the correct workspace.
        /// </summary>
        private async Task UpdatePathsToRemoteFilesAsync(CollaborationSession session)
        {
            var(remoteRootPaths, externalPaths) = await GetLocalPathsOfRemoteRootsAsync(session)
                                                  .ConfigureAwait(false);

            // Make sure we update our references to the remote roots and iterate RDT only one at a time.
            using (
                await s_RemotePathsGate
                .DisposableWaitAsync(CancellationToken.None)
                .ConfigureAwait(false)
                )
            {
                if (
                    IsRemoteSession &&
                    (
                        !_remoteWorkspaceRootPaths.Equals(remoteRootPaths) ||
                        !_registeredExternalPaths.Equals(externalPaths)
                    )
                    )
                {
                    _remoteWorkspaceRootPaths = remoteRootPaths;
                    _registeredExternalPaths  = externalPaths;
                    await RefreshAllFilesAsync().ConfigureAwait(false);
                }
            }
        }
예제 #16
0
        public async Task <bool> TryInvokeAsync(string targetName, params object[] arguments)
        {
            using (await _gate.DisposableWaitAsync(_cancellationToken).ConfigureAwait(false))
            {
                var connection = await TryGetConnection_NoLockAsync().ConfigureAwait(false);

                if (connection == null)
                {
                    return(false);
                }

                await connection.InvokeAsync(targetName, arguments).ConfigureAwait(false);

                return(true);
            }
        }
            private async Task ProcessExitedHandlerAsync()
            {
                try
                {
                    using (await _disposeSemaphore.DisposableWaitAsync().ConfigureAwait(false))
                    {
                        if (_processExitHandlerStatus == ProcessExitHandlerStatus.Hooked)
                        {
                            Process.Exited           -= ProcessExitedHandler;
                            _processExitHandlerStatus = ProcessExitHandlerStatus.Handled;
                            // Should set _processExitHandlerStatus before calling OnProcessExited to avoid deadlocks.
                            // Calling the host should be within the lock to prevent its disposing during the execution.
                        }
                    }

                    var host = _host;
                    if (host != null)
                    {
                        await host.OnProcessExited(Process).ConfigureAwait(false);
                    }
                }
                catch (Exception e) when(FatalError.Report(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
        public async Task <WebClientResult> Get(string url, int retryCount = 10)
        {
            Task <string> MakeRequest()
            {
                _webClient.Headers["User-Agent"] =
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0";
                var result = _webClient.DownloadString(new Uri(url));

                return(Task.FromResult(result));
            }

            using (await _semaphoreSlim.DisposableWaitAsync(TimeSpan.FromMinutes(10)))
            {
                return(await RetryableRequest(MakeRequest, retryCount));
            }
        }
예제 #19
0
 private async Task <ISymbolSearchUpdateEngine> GetEngineAsync(CancellationToken cancellationToken)
 {
     using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
     {
         return(_lazyUpdateEngine ??= await SymbolSearchUpdateEngineFactory.CreateEngineAsync(
                    _workspace, _logService, _progressService, cancellationToken).ConfigureAwait(false));
     }
 }
예제 #20
0
 private async Task <MSB.Execution.BuildResult> BuildAsync(MSB.Execution.BuildRequestData requestData, CancellationToken cancellationToken)
 {
     // only allow one build to use the default build manager at a time
     using (await s_buildManagerLock.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
     {
         return(await BuildAsync(MSB.Execution.BuildManager.DefaultBuildManager, requestData, cancellationToken).ConfigureAwait(false));
     }
 }
예제 #21
0
        public async Task UpdatePrimaryBranchSolutionAsync(AssetProvider assetProvider, Checksum solutionChecksum, int workspaceVersion, CancellationToken cancellationToken)
        {
            var currentSolution = CurrentSolution;

            var currentSolutionChecksum = await currentSolution.State.GetChecksumAsync(cancellationToken).ConfigureAwait(false);

            if (currentSolutionChecksum == solutionChecksum)
            {
                return;
            }

            using (await _availableSolutionsGate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                var solution = await CreateSolution_NoLockAsync(assetProvider, solutionChecksum, fromPrimaryBranch : true, workspaceVersion, currentSolution, cancellationToken).ConfigureAwait(false);

                _primaryBranchSolutionWithChecksum = Tuple.Create(solutionChecksum, solution);
            }
        }
예제 #22
0
        private async Task <KeepAliveSession> TryGetKeepAliveSessionAsync(RemoteHostClient client, CancellationToken cancellationToken)
        {
            using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                if (_sessionDoNotAccessDirectly == null)
                {
                    _sessionDoNotAccessDirectly = await client.TryCreateCodeAnalysisKeepAliveSessionAsync(cancellationToken).ConfigureAwait(false);
                }

                return(_sessionDoNotAccessDirectly);
            }
        }
        private async Task <ISymbolSearchUpdateEngine> GetEngine(CancellationToken cancellationToken)
        {
            using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                if (_updateEngine == null)
                {
                    _updateEngine = await SymbolSearchUpdateEngineFactory.CreateEngineAsync(
                        _workspace, _logService, cancellationToken).ConfigureAwait(false);
                }

                return(_updateEngine);
            }
        }
        private static async Task <bool> DelayAsync(SemaphoreSlim semaphoreSlim)
        {
            await Task.Delay(1000);

            var random = new Random();

            using (await semaphoreSlim.DisposableWaitAsync(TimeSpan.MaxValue))
            {
                await Task.Delay(random.Next(1, 100));

                return(true);
            }
        }
 public static async Task ExecuteWithinLockAsync(this SemaphoreSlim semaphore, JoinableTaskCollection collection, JoinableTaskFactory factory, Action action)
 {
     // Join the caller to our collection, so that if the lock is already held by another task that needs UI
     // thread access we don't deadlock if we're also being waited on by the UI thread. For example, when CPS
     // is draining critical tasks and is waiting us.
     using (collection.Join())
     {
         using (await semaphore.DisposableWaitAsync().ConfigureAwait(false))
         {
             action();
         }
     }
 }
예제 #26
0
        public override async Task OnDefinitionFoundAsync(DefinitionItem definition)
        {
            using (await _semaphore.DisposableWaitAsync(CancellationToken).ConfigureAwait(false))
            {
                if (_definitionToId.ContainsKey(definition))
                {
                    return;
                }

                // Assigning a new id to the definition
                _id++;
                _definitionToId.Add(definition, _id);

                // VSReferenceItem currently doesn't support the ClassifiedTextElement type for DefinitionText,
                // so for now we just pass in a string.
                // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/918138
                var classifiedText = definition.GetClassifiedText();

                using var pd = PooledStringBuilder.GetInstance(out var pooledBuilder);
                foreach (var text in classifiedText.Runs)
                {
                    pooledBuilder.Append(text.Text);
                }

                var definitionText = pooledBuilder.ToString();

                // Creating a new VSReferenceItem for the definition
                var definitionItem = await GenerateVSReferenceItemAsync(
                    _id, definitionId : _id, _document, _position, definition.SourceSpans.FirstOrDefault(),
                    definition.DisplayableProperties, _metadataAsSourceFileService, definitionText,
                    symbolUsageInfo : null, CancellationToken).ConfigureAwait(false);

                if (definitionItem != null)
                {
                    AddToReferencesToReport_MustBeCalledUnderLock(definitionItem);
                }
            }
        }
예제 #27
0
        private async Task <KeepAliveSession> TryGetKeepAliveSessionAsync(RemoteHostClient client, CancellationToken cancellation)
        {
            using (await _gate.DisposableWaitAsync(cancellation).ConfigureAwait(false))
            {
                if (_sessionDoNotAccessDirectly == null)
                {
                    // we give cancellation none here since the cancellation will cause KeepAlive session to be shutdown
                    // when raised
                    _sessionDoNotAccessDirectly = await client.TryCreateCodeAnalysisKeepAliveSessionAsync(CancellationToken.None).ConfigureAwait(false);
                }

                return(_sessionDoNotAccessDirectly);
            }
        }
예제 #28
0
            private async Task UpdateSolutionChecksumAsync(CancellationToken cancellationToken)
            {
                using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
                {
                    // hold onto previous snapshot
                    var previousSnapshot = _lastSnapshot;

                    // create a new one (incrementally update the snapshot)
                    _lastSnapshot = await _checksumService.CreateChecksumAsync(_service.Workspace.CurrentSolution, cancellationToken).ConfigureAwait(false);

                    // let old one go.
                    previousSnapshot?.Dispose();
                }
            }
예제 #29
0
        private async Task UpdateSeriesIfNecessaryAsync(TvDbSeries series)
        {
            bool ownsTask = false;
            Task update   = null;

            using (await ioLock.DisposableWaitAsync())
            {
                if (updates.ContainsKey(series))
                {
                    update = updates[series];
                }

                var needsUpdating = (series.Updated == null) || (DateTime.Now - series.Updated > TimeSpan.FromHours(3));
                if (needsUpdating)
                {
                    update = UpdateSeriesAsync(series);
                    updates.Add(series, update);
                    ownsTask = true;
                }
            }
            if (update != null)
            {
                await update;
                if (ownsTask)
                {
                    using (await ioLock.DisposableWaitAsync())
                    {
                        updates.Remove(series);
                        if (series.IsSubscribed)
                        {
                            storageManager.Save(series);
                        }
                    }
                }
            }
        }
예제 #30
0
            // More complicated forwarding functions.  These need to map from the symbols
            // used by the FAR engine to the INavigableItems used by the streaming FAR
            // feature.

            private async Task <DefinitionItem> GetDefinitionItemAsync(SymbolAndProjectId definition)
            {
                using (await _gate.DisposableWaitAsync(_context.CancellationToken).ConfigureAwait(false))
                {
                    if (!_definitionToItem.TryGetValue(definition.Symbol, out var definitionItem))
                    {
                        definitionItem = await definition.Symbol.ToClassifiedDefinitionItemAsync(
                            _solution.GetProject(definition.ProjectId), includeHiddenLocations : false, cancellationToken : _context.CancellationToken).ConfigureAwait(false);

                        _definitionToItem[definition.Symbol] = definitionItem;
                    }

                    return(definitionItem);
                }
            }