in src/Microsoft.VisualStudio.Threading/JoinableTaskDependencyGraph.cs [948:1021]
private static void RemoveDependingSynchronousTask(IJoinableTaskDependent taskOrCollection, JoinableTask task, HashSet<IJoinableTaskDependent>? reachableNodesReadOnlySet, ref HashSet<IJoinableTaskDependent>? remainingDependentNodes)
{
Requires.NotNull(taskOrCollection, nameof(taskOrCollection));
Requires.NotNull(task, nameof(task));
ref JoinableTaskDependentData data = ref taskOrCollection.GetJoinableTaskDependentData();
DependentSynchronousTask? previousTaskTracking = null;
DependentSynchronousTask? currentTaskTracking = data.dependingSynchronousTaskTracking;
bool removed = false;
while (currentTaskTracking is object)
{
if (currentTaskTracking.SynchronousTask == task)
{
if (--currentTaskTracking.ReferenceCount > 0)
{
if (reachableNodesReadOnlySet is object)
{
if (!reachableNodesReadOnlySet.Contains(taskOrCollection))
{
currentTaskTracking.ReferenceCount = 0;
}
}
}
if (currentTaskTracking.ReferenceCount == 0)
{
removed = true;
if (previousTaskTracking is object)
{
previousTaskTracking.Next = currentTaskTracking.Next;
}
else
{
data.dependingSynchronousTaskTracking = currentTaskTracking.Next;
}
}
if (reachableNodesReadOnlySet is null)
{
// if a node doesn't have dependencies, it cannot be a part of a dependency circle.
if (removed || taskOrCollection.GetJoinableTaskDependentData().HasNoChildDependentNode)
{
if (remainingDependentNodes is object)
{
remainingDependentNodes.Remove(taskOrCollection);
}
}
else
{
if (remainingDependentNodes is null)
{
remainingDependentNodes = new HashSet<IJoinableTaskDependent>();
}
remainingDependentNodes.Add(taskOrCollection);
}
}
break;
}
previousTaskTracking = currentTaskTracking;
currentTaskTracking = currentTaskTracking.Next;
}
if (removed && data.childDependentNodes is object)
{
foreach (KeyValuePair<IJoinableTaskDependent, int> item in data.childDependentNodes)
{
RemoveDependingSynchronousTask(item.Key, task, reachableNodesReadOnlySet, ref remainingDependentNodes);
}
}
}