Skip to content

Commit

Permalink
Avoid extra JTF collection/factory
Browse files Browse the repository at this point in the history
`LanguageServiceHost` uses its own JTF collection and factory to track its work.

This class derives from `OnceInitializedOnceDisposedAsync`, which also has its own collection and factory.

@lifengl recently noticed this while investigating a hang and suggested that we reuse the base class's objects to reduce allocations and potentially even help avoid deadlocks.
  • Loading branch information
drewnoakes committed Dec 16, 2024
1 parent 5f3636c commit d0e1f7a
Showing 1 changed file with 4 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ internal sealed class LanguageServiceHost : OnceInitializedOnceDisposedAsync, IP
private readonly IUnconfiguredProjectTasksService _tasksService;
private readonly ISafeProjectGuidService _projectGuidService;
private readonly IProjectFaultHandlerService _projectFaultHandler;
private readonly JoinableTaskCollection _joinableTaskCollection;
private readonly JoinableTaskFactory _joinableTaskFactory;
private readonly AsyncLazy<bool> _isEnabled;

private DisposableBag? _disposables;
Expand Down Expand Up @@ -88,10 +86,6 @@ public LanguageServiceHost(
|| await vsShell.IsPopulateSolutionCacheModeAsync();
},
threadingService.JoinableTaskFactory);

_joinableTaskCollection = threadingService.JoinableTaskContext.CreateCollection();
_joinableTaskCollection.DisplayName = "LanguageServiceHostTasks";
_joinableTaskFactory = new JoinableTaskFactory(_joinableTaskCollection);
}

public Task LoadAsync()
Expand Down Expand Up @@ -175,7 +169,7 @@ protected override async Task InitializeCoreAsync(CancellationToken cancellation
linkOptions: DataflowOption.PropagateCompletion,
cancellationToken: cancellationToken),

ProjectDataSources.JoinUpstreamDataSources(_joinableTaskFactory, _projectFaultHandler, _activeConfiguredProjectProvider, _activeConfigurationGroupSubscriptionService),
ProjectDataSources.JoinUpstreamDataSources(JoinableFactory, _projectFaultHandler, _activeConfiguredProjectProvider, _activeConfigurationGroupSubscriptionService),

new DisposableDelegate(() =>
{
Expand Down Expand Up @@ -211,7 +205,7 @@ async Task OnSlicesChangedAsync(IProjectVersionedValue<(ConfiguredProject Active
Guid projectGuid = await _projectGuidService.GetProjectGuidAsync(cancellationToken);

// New slice. Create a workspace for it.
workspace = _workspaceFactory.Create(source, slice, _joinableTaskCollection, _joinableTaskFactory, projectGuid, cancellationToken);
workspace = _workspaceFactory.Create(source, slice, JoinableCollection, JoinableFactory, projectGuid, cancellationToken);

if (workspace is null)
{
Expand Down Expand Up @@ -282,7 +276,7 @@ public async Task WhenInitialized(CancellationToken token)
{
await ValidateEnabledAsync(token);

using (_joinableTaskCollection.Join())
using (JoinableCollection.Join())
{
await _firstPrimaryWorkspaceSet.Task.WithCancellation(token);
}
Expand Down Expand Up @@ -350,7 +344,7 @@ public async Task AfterLoadInitialConfigurationAsync()
// Ensure the project is not considered loaded until our first publication.
Task result = _tasksService.PrioritizedProjectLoadedInHostAsync(async () =>
{
using (_joinableTaskCollection.Join())
using (JoinableCollection.Join())
{
await WhenInitialized(_tasksService.UnloadCancellationToken);
}
Expand Down

0 comments on commit d0e1f7a

Please sign in to comment.