Merge pull request #488 from Cysharp/revert-445-fix-wait-async

Revert "Fixed https://github.com/Cysharp/UniTask/issues/444"
pull/489/head
hadashiA 2023-09-01 20:08:55 +09:00 committed by GitHub
commit c1042b32b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 113 deletions

View File

@ -20,6 +20,8 @@ namespace Cysharp.Threading.Tasks
{ {
ITriggerHandler<T> head; // head.prev is last ITriggerHandler<T> head; // head.prev is last
ITriggerHandler<T> iteratingHead; ITriggerHandler<T> iteratingHead;
bool preserveRemoveSelf;
ITriggerHandler<T> iteratingNode; ITriggerHandler<T> iteratingNode;
void LogError(Exception ex) void LogError(Exception ex)
@ -42,7 +44,6 @@ namespace Cysharp.Threading.Tasks
while (h != null) while (h != null)
{ {
iteratingNode = h; iteratingNode = h;
var next = h.Next;
try try
{ {
@ -54,7 +55,18 @@ namespace Cysharp.Threading.Tasks
Remove(h); Remove(h);
} }
h = next; if (preserveRemoveSelf)
{
preserveRemoveSelf = false;
iteratingNode = null;
var next = h.Next;
Remove(h);
h = next;
}
else
{
h = h.Next;
}
} }
iteratingNode = null; iteratingNode = null;
@ -84,7 +96,8 @@ namespace Cysharp.Threading.Tasks
{ {
LogError(ex); LogError(ex);
} }
preserveRemoveSelf = false;
iteratingNode = null; iteratingNode = null;
var next = h.Next; var next = h.Next;
Remove(h); Remove(h);
@ -118,7 +131,8 @@ namespace Cysharp.Threading.Tasks
{ {
LogError(ex); LogError(ex);
} }
preserveRemoveSelf = false;
iteratingNode = null; iteratingNode = null;
var next = h.Next; var next = h.Next;
Remove(h); Remove(h);
@ -152,7 +166,8 @@ namespace Cysharp.Threading.Tasks
{ {
LogError(ex); LogError(ex);
} }
preserveRemoveSelf = false;
iteratingNode = null; iteratingNode = null;
var next = h.Next; var next = h.Next;
Remove(h); Remove(h);
@ -225,64 +240,72 @@ namespace Cysharp.Threading.Tasks
public void Remove(ITriggerHandler<T> handler) public void Remove(ITriggerHandler<T> handler)
{ {
if (handler == null) throw new ArgumentNullException(nameof(handler)); if (handler == null) throw new ArgumentNullException(nameof(handler));
var prev = handler.Prev;
var next = handler.Next;
if (next != null) if (iteratingNode != null && iteratingNode == handler)
{ {
next.Prev = prev; // if remove self, reserve remove self after invoke completed.
} preserveRemoveSelf = true;
if (handler == head)
{
head = next;
}
else if (handler == iteratingHead)
{
iteratingHead = next;
} }
else else
{ {
// when handler is head, prev indicate last so don't use it. var prev = handler.Prev;
if (prev != null) var next = handler.Next;
{
prev.Next = next;
}
}
if (head != null) if (next != null)
{
if (head.Prev == handler)
{ {
if (prev != head) next.Prev = prev;
}
if (handler == head)
{
head = next;
}
else if (handler == iteratingHead)
{
iteratingHead = next;
}
else
{
// when handler is head, prev indicate last so don't use it.
if (prev != null)
{ {
head.Prev = prev; prev.Next = next;
}
else
{
head.Prev = null;
} }
} }
}
if (iteratingHead != null) if (head != null)
{
if (iteratingHead.Prev == handler)
{ {
if (prev != iteratingHead.Prev) if (head.Prev == handler)
{ {
iteratingHead.Prev = prev; if (prev != head)
} {
else head.Prev = prev;
{ }
iteratingHead.Prev = null; else
{
head.Prev = null;
}
} }
} }
}
handler.Prev = null; if (iteratingHead != null)
handler.Next = null; {
if (iteratingHead.Prev == handler)
{
if (prev != iteratingHead.Prev)
{
iteratingHead.Prev = prev;
}
else
{
iteratingHead.Prev = null;
}
}
}
handler.Prev = null;
handler.Next = null;
}
} }
} }
} }

View File

@ -1,63 +0,0 @@
using Cysharp.Threading.Tasks;
using FluentAssertions;
using System;
using System.Collections;
using System.Threading;
using UnityEngine.TestTools;
namespace Cysharp.Threading.TasksTests
{
public class AsyncReactivePropertyTest
{
private int _callCounter;
[UnityTest]
public IEnumerator WaitCancelWait() => UniTask.ToCoroutine(async () =>
{
// Test case for https://github.com/Cysharp/UniTask/issues/444
var property = new AsyncReactiveProperty<int>(0);
var cts1 = new CancellationTokenSource();
var cts2 = new CancellationTokenSource();
WaitForProperty(property, cts1.Token);
WaitForProperty(property, cts2.Token);
_callCounter = 0;
property.Value = 1;
_callCounter.Should().Be(2);
cts2.Cancel();
cts2.Dispose();
cts1.Cancel();
cts1.Dispose();
var cts3 = new CancellationTokenSource();
WaitForProperty(property, cts3.Token);
_callCounter = 0;
property.Value = 2;
_callCounter.Should().Be(1);
cts3.Cancel();
cts3.Dispose();
await UniTask.CompletedTask;
});
private async void WaitForProperty(AsyncReactiveProperty<int> property, CancellationToken token)
{
while (true)
{
try
{
await property.WaitAsync(token);
_callCounter++;
}
catch (OperationCanceledException)
{
break;
}
}
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 27665955eefb4448969b8cc4dd204600
timeCreated: 1676129650