提交 bfadc397 编写于 作者: M Matt Warren 提交者: GitHub

Merge pull request #14918 from mattwar/Bug11726

simplify syntax tree task caching
...@@ -139,60 +139,35 @@ public bool SupportsSemanticModel ...@@ -139,60 +139,35 @@ public bool SupportsSemanticModel
} }
} }
private Task<SyntaxTree> GetExistingSyntaxTreeTask() /// <summary>
/// Gets the <see cref="SyntaxTree" /> for this document asynchronously.
/// </summary>
public Task<SyntaxTree> GetSyntaxTreeAsync(CancellationToken cancellationToken = default(CancellationToken))
{ {
if (_syntaxTreeResultTask != null) // If the language doesn't support getting syntax trees for a document, then bail out immediately.
if (!this.SupportsSyntaxTree)
{ {
return _syntaxTreeResultTask; return SpecializedTasks.Default<SyntaxTree>();
} }
// First see if we already have a semantic model computed. If so, we can just return // if we have a cached result task use it
// that syntax tree. if (_syntaxTreeResultTask != null)
SemanticModel semanticModel;
if (TryGetSemanticModel(out semanticModel))
{ {
// PERF: This is a hot code path, so cache the result to reduce allocations
var result = Task.FromResult(semanticModel.SyntaxTree);
Interlocked.CompareExchange(ref _syntaxTreeResultTask, result, null);
return _syntaxTreeResultTask; return _syntaxTreeResultTask;
} }
// second, see whether we already computed the tree, if we already did, return the cache // check to see if we already have the tree before actually going async
SyntaxTree tree; SyntaxTree tree;
if (TryGetSyntaxTree(out tree)) if (TryGetSyntaxTree(out tree))
{ {
if (_syntaxTreeResultTask == null) // stash a completed result task for this value for the next request (to reduce extraneous allocations of tasks)
{ // don't use the actual async task because it depends on a specific cancellation token
var result = Task.FromResult(tree); // its okay to cache the task and hold onto the SyntaxTree, because the DocumentState already keeps the SyntaxTree alive.
Interlocked.CompareExchange(ref _syntaxTreeResultTask, result, null); Interlocked.CompareExchange(ref _syntaxTreeResultTask, Task.FromResult(tree), null);
}
return _syntaxTreeResultTask; return _syntaxTreeResultTask;
} }
return null; // do it async for real.
}
/// <summary>
/// Gets the <see cref="SyntaxTree" /> for this document asynchronously.
/// </summary>
public Task<SyntaxTree> GetSyntaxTreeAsync(CancellationToken cancellationToken = default(CancellationToken))
{
// If the language doesn't support getting syntax trees for a document, then bail out
// immediately.
if (!this.SupportsSyntaxTree)
{
return SpecializedTasks.Default<SyntaxTree>();
}
var syntaxTreeTask = GetExistingSyntaxTreeTask();
if (syntaxTreeTask != null)
{
return syntaxTreeTask;
}
// we can't cache this result, since internally it uses AsyncLazy which
// care about cancellation token
return DocumentState.GetSyntaxTreeAsync(cancellationToken); return DocumentState.GetSyntaxTreeAsync(cancellationToken);
} }
...@@ -203,15 +178,6 @@ internal SyntaxTree GetSyntaxTreeSynchronously(CancellationToken cancellationTok ...@@ -203,15 +178,6 @@ internal SyntaxTree GetSyntaxTreeSynchronously(CancellationToken cancellationTok
return null; return null;
} }
// if we already have a stask for getting this syntax tree, and the task
// has completed, then we can just return that value.
var syntaxTreeTask = GetExistingSyntaxTreeTask();
if (syntaxTreeTask?.Status == TaskStatus.RanToCompletion)
{
return syntaxTreeTask.Result;
}
// Otherwise defer to our state to get this value.
return DocumentState.GetSyntaxTree(cancellationToken); return DocumentState.GetSyntaxTree(cancellationToken);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册