Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async experimentation service #30929

Closed
wants to merge 5 commits into from

Conversation

sharwell
Copy link
Member

@sharwell sharwell commented Nov 2, 2018

This pull request builds on #30916 by converting the service to asynchronous with a fully free-threaded constructor.

private readonly MethodInfo _isCachedFlightEnabledInfo;
private readonly IAsyncServiceProvider _asyncServiceProvider;

private Optional<Func<string, bool>> _isCachedFlightEnabled;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this is in master, i would think the risk woudl be lower for trying something like AsyncLazy (either roslyn's or JTFs). I'd still prefer that myself.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AsyncLazy includes a single-invocation guarantee for the initializer at the expense of complexity. This feature does not rely on this constraint.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, complexity is in the eye of the beholder :) When i see lazy intialization code that doesn't go through one of these helpers, then you have to then spend cycles going "ok... is this going to be ok in the presence of multiple initializers coming in". Sometimes an abstraction/indirection can help toward reducing complexity.

That said, i'm not going to press on this. This is all self contained, and if you feel that the current approach is fine, that's ok with me. I might request though that we put a comment in the code explicitly stating that we've though about the case where this is called into from multiple threads, and it will still be safe in that case since it will just mean in rare cases we get a little extra computation that is then thrown away. The comment at least makes it clear we thought about this though. Thanks!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasonmalinowski I think we need a helper for asynchronous optimistic initialization...

Basically the asynchronous form of LazyInitializer.EnsureInitialized<T>(T, Func<T>).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'd use AsyncLazy, if only because it means the field can be made readonly and nobody can access the other thing by accident. If this was perf-sensitive then maybe I'd care.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p.s.: I should say "AsyncLazy"-like thing, as ours today probably isn't safe for JTF.

@@ -69,7 +72,7 @@ public void OnSuggestedActionExecuted(SuggestedAction action)
!IsVsixInstalled() &&
IsCandidate())
{
ShowInfoBarIfNecessary();
ThreadingContext.JoinableTaskFactory.Run(() => ShowInfoBarIfNecessaryAsync(CancellationToken.None));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we (manually) test to make sure this works safely and doesn't like deadlock or anything :D

{
ThisCanBeCalledOnAnyThread();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are we able to prevent additional calls on this that aren't using JTF? I agree this is a good and appropriate use in the Roslyn codebase, although I assume we've already asked the team that owns SVsExperimentationService what it would take to make it fully free-threaded? It's just that right now this is special in our codebase and different than everything else, which almost guarantees a bug at some point.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are we able to prevent additional calls on this that aren't using JTF?

I don't understand this question.

although I assume we've already asked the team that owns SVsExperimentationService what it would take to make it fully free-threaded

In this pull request, SVsExperimentationService is used under the assumption that it is already free-threaded. This behavior is carried over from the behavior before this pull request.

It's just that right now this is special in our codebase and different than everything else,

I don't understand this comment.

@sharwell
Copy link
Member Author

sharwell commented Nov 7, 2018

💡 Can remove the explicit instantiation of this service now:

_workspace.Services.GetService<IExperimentationService>();

@sharwell sharwell changed the base branch from master to dev16.0-preview2 November 8, 2018 03:20
@sharwell
Copy link
Member Author

sharwell commented Nov 8, 2018

I'm waiting to clean this up after dev16.0.x merges forward to dev16.0-preview2.

@jasonmalinowski jasonmalinowski changed the base branch from dev16.0-preview2 to master November 16, 2018 19:43
Base automatically changed from master to main March 3, 2021 23:51
@sharwell
Copy link
Member Author

This is no longer applicable (#55902)

@sharwell sharwell closed this May 26, 2022
@sharwell sharwell deleted the async-experimentation branch May 26, 2022 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants