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

Merge pull request #14918 from mattwar/Bug11726

simplify syntax tree task caching
......@@ -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
// that syntax tree.
SemanticModel semanticModel;
if (TryGetSemanticModel(out semanticModel))
// if we have a cached result task use it
if (_syntaxTreeResultTask != null)
{
// 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;
}
// 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;
if (TryGetSyntaxTree(out tree))
{
if (_syntaxTreeResultTask == null)
{
var result = Task.FromResult(tree);
Interlocked.CompareExchange(ref _syntaxTreeResultTask, result, 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
// its okay to cache the task and hold onto the SyntaxTree, because the DocumentState already keeps the SyntaxTree alive.
Interlocked.CompareExchange(ref _syntaxTreeResultTask, Task.FromResult(tree), null);
return _syntaxTreeResultTask;
}
return null;
}
/// <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
// do it async for real.
return DocumentState.GetSyntaxTreeAsync(cancellationToken);
}
......@@ -203,15 +178,6 @@ internal SyntaxTree GetSyntaxTreeSynchronously(CancellationToken cancellationTok
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);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册