AsyncTrigger returns MoveNext -> false when destroyed
parent
efaf3ee8f5
commit
7a306118f5
|
@ -4,26 +4,25 @@ using System.Threading;
|
|||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public interface ITriggerEvent<T>
|
||||
public interface ITriggerHandler<T>
|
||||
{
|
||||
void SetResult(T value);
|
||||
void SetCanceled(CancellationToken cancellationToken);
|
||||
void Add(IResolveCancelPromise<T> handler);
|
||||
void Remove(IResolveCancelPromise<T> handler);
|
||||
void OnNext(T value);
|
||||
void OnCanceled(CancellationToken cancellationToken);
|
||||
void OnCompleted();
|
||||
}
|
||||
|
||||
// be careful to use, itself is struct.
|
||||
public struct TriggerEvent<T> : ITriggerEvent<T>
|
||||
public struct TriggerEvent<T>
|
||||
{
|
||||
// optimize: many cases, handler is single.
|
||||
IResolveCancelPromise<T> singleHandler;
|
||||
ITriggerHandler<T> singleHandler;
|
||||
|
||||
IResolveCancelPromise<T>[] handlers;
|
||||
ITriggerHandler<T>[] handlers;
|
||||
|
||||
// when running(in TrySetResult), does not add immediately.
|
||||
// when running(in TrySetResult), does not add immediately(trampoline).
|
||||
bool isRunning;
|
||||
IResolveCancelPromise<T> waitHandler;
|
||||
MinimumQueue<IResolveCancelPromise<T>> waitQueue;
|
||||
ITriggerHandler<T> waitHandler;
|
||||
MinimumQueue<ITriggerHandler<T>> waitQueue;
|
||||
|
||||
public void SetResult(T value)
|
||||
{
|
||||
|
@ -33,7 +32,7 @@ namespace Cysharp.Threading.Tasks
|
|||
{
|
||||
try
|
||||
{
|
||||
singleHandler.TrySetResult(value);
|
||||
singleHandler.OnNext(value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -53,7 +52,7 @@ namespace Cysharp.Threading.Tasks
|
|||
{
|
||||
try
|
||||
{
|
||||
handlers[i].TrySetResult(value);
|
||||
handlers[i].OnNext(value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -94,7 +93,7 @@ namespace Cysharp.Threading.Tasks
|
|||
{
|
||||
try
|
||||
{
|
||||
((ICancelPromise)singleHandler).TrySetCanceled(cancellationToken);
|
||||
(singleHandler).OnCanceled(cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -114,7 +113,7 @@ namespace Cysharp.Threading.Tasks
|
|||
{
|
||||
try
|
||||
{
|
||||
((ICancelPromise)handlers[i]).TrySetCanceled(cancellationToken);
|
||||
(handlers[i]).OnCanceled(cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -147,7 +146,68 @@ namespace Cysharp.Threading.Tasks
|
|||
}
|
||||
}
|
||||
|
||||
public void Add(IResolveCancelPromise<T> handler)
|
||||
public void SetCompleted()
|
||||
{
|
||||
isRunning = true;
|
||||
|
||||
if (singleHandler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
(singleHandler).OnCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
UnityEngine.Debug.LogException(ex);
|
||||
#else
|
||||
Console.WriteLine(ex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (handlers != null)
|
||||
{
|
||||
for (int i = 0; i < handlers.Length; i++)
|
||||
{
|
||||
if (handlers[i] != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
(handlers[i]).OnCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
UnityEngine.Debug.LogException(ex);
|
||||
#else
|
||||
Console.WriteLine(ex);
|
||||
#endif
|
||||
handlers[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isRunning = false;
|
||||
|
||||
if (waitHandler != null)
|
||||
{
|
||||
var h = waitHandler;
|
||||
waitHandler = null;
|
||||
Add(h);
|
||||
}
|
||||
|
||||
if (waitQueue != null)
|
||||
{
|
||||
while (waitQueue.Count != 0)
|
||||
{
|
||||
Add(waitQueue.Dequeue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(ITriggerHandler<T> handler)
|
||||
{
|
||||
if (isRunning)
|
||||
{
|
||||
|
@ -159,7 +219,7 @@ namespace Cysharp.Threading.Tasks
|
|||
|
||||
if (waitQueue == null)
|
||||
{
|
||||
waitQueue = new MinimumQueue<IResolveCancelPromise<T>>(4);
|
||||
waitQueue = new MinimumQueue<ITriggerHandler<T>>(4);
|
||||
}
|
||||
waitQueue.Enqueue(handler);
|
||||
return;
|
||||
|
@ -173,7 +233,7 @@ namespace Cysharp.Threading.Tasks
|
|||
{
|
||||
if (handlers == null)
|
||||
{
|
||||
handlers = new IResolveCancelPromise<T>[4];
|
||||
handlers = new ITriggerHandler<T>[4];
|
||||
}
|
||||
|
||||
// check empty
|
||||
|
@ -195,15 +255,15 @@ namespace Cysharp.Threading.Tasks
|
|||
}
|
||||
}
|
||||
|
||||
static void EnsureCapacity(ref IResolveCancelPromise<T>[] array)
|
||||
static void EnsureCapacity(ref ITriggerHandler<T>[] array)
|
||||
{
|
||||
var newSize = array.Length * 2;
|
||||
var newArray = new IResolveCancelPromise<T>[newSize];
|
||||
var newArray = new ITriggerHandler<T>[newSize];
|
||||
Array.Copy(array, 0, newArray, 0, array.Length);
|
||||
array = newArray;
|
||||
}
|
||||
|
||||
public void Remove(IResolveCancelPromise<T> handler)
|
||||
public void Remove(ITriggerHandler<T> handler)
|
||||
{
|
||||
if (singleHandler == handler)
|
||||
{
|
||||
|
|
|
@ -24,10 +24,10 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||
if (calledDestroy) return;
|
||||
calledDestroy = true;
|
||||
|
||||
triggerEvent.SetCanceled(CancellationToken.None);
|
||||
triggerEvent.SetCompleted();
|
||||
}
|
||||
|
||||
internal void AddHandler(IResolveCancelPromise<T> handler)
|
||||
internal void AddHandler(ITriggerHandler<T> handler)
|
||||
{
|
||||
if (!calledAwake)
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||
triggerEvent.Add(handler);
|
||||
}
|
||||
|
||||
internal void RemoveHandler(IResolveCancelPromise<T> handler)
|
||||
internal void RemoveHandler(ITriggerHandler<T> handler)
|
||||
{
|
||||
if (!calledAwake)
|
||||
{
|
||||
|
@ -57,7 +57,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||
return new AsyncTriggerEnumerator(this, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class AsyncTriggerEnumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, IResolveCancelPromise<T>
|
||||
sealed class AsyncTriggerEnumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, ITriggerHandler<T>
|
||||
{
|
||||
static Action<object> cancellationCallback = CancellationCallback;
|
||||
|
||||
|
@ -73,15 +73,20 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||
public void OnCanceled(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return completionSource.TrySetCanceled(cancellationToken);
|
||||
completionSource.TrySetCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
public bool TrySetResult(T value)
|
||||
public void OnNext(T value)
|
||||
{
|
||||
Current = value;
|
||||
return completionSource.TrySetResult(true);
|
||||
completionSource.TrySetResult(true);
|
||||
}
|
||||
|
||||
public void OnCompleted()
|
||||
{
|
||||
completionSource.TrySetResult(false);
|
||||
}
|
||||
|
||||
static void CancellationCallback(object state)
|
||||
|
@ -164,7 +169,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||
}
|
||||
}
|
||||
|
||||
public sealed partial class AsyncTriggerHandler<T> : IUniTaskSource<T>, IResolveCancelPromise<T>, IDisposable
|
||||
public sealed partial class AsyncTriggerHandler<T> : IUniTaskSource<T>, ITriggerHandler<T>, IDisposable
|
||||
{
|
||||
static Action<object> cancellationCallback = CancellationCallback;
|
||||
|
||||
|
@ -253,14 +258,19 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||
}
|
||||
}
|
||||
|
||||
bool IResolvePromise<T>.TrySetResult(T result)
|
||||
void ITriggerHandler<T>.OnNext(T value)
|
||||
{
|
||||
return core.TrySetResult(result);
|
||||
core.TrySetResult(value);
|
||||
}
|
||||
|
||||
bool ICancelPromise.TrySetCanceled(CancellationToken cancellationToken)
|
||||
void ITriggerHandler<T>.OnCanceled(CancellationToken cancellationToken)
|
||||
{
|
||||
return core.TrySetCanceled(cancellationToken);
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
void ITriggerHandler<T>.OnCompleted()
|
||||
{
|
||||
core.TrySetCanceled(CancellationToken.None);
|
||||
}
|
||||
|
||||
void IUniTaskSource.GetResult(short token)
|
||||
|
|
|
@ -38,14 +38,6 @@ namespace Cysharp.Threading.Tasks
|
|||
{
|
||||
}
|
||||
|
||||
public interface IResolveCancelPromise : IResolvePromise, ICancelPromise
|
||||
{
|
||||
}
|
||||
|
||||
public interface IResolveCancelPromise<T> : IResolvePromise<T>, ICancelPromise
|
||||
{
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct UniTaskCompletionSourceCore<TResult>
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue