AsyncTrigger returns MoveNext -> false when destroyed
parent
efaf3ee8f5
commit
7a306118f5
|
@ -4,26 +4,25 @@ using System.Threading;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public interface ITriggerEvent<T>
|
public interface ITriggerHandler<T>
|
||||||
{
|
{
|
||||||
void SetResult(T value);
|
void OnNext(T value);
|
||||||
void SetCanceled(CancellationToken cancellationToken);
|
void OnCanceled(CancellationToken cancellationToken);
|
||||||
void Add(IResolveCancelPromise<T> handler);
|
void OnCompleted();
|
||||||
void Remove(IResolveCancelPromise<T> handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// be careful to use, itself is struct.
|
// be careful to use, itself is struct.
|
||||||
public struct TriggerEvent<T> : ITriggerEvent<T>
|
public struct TriggerEvent<T>
|
||||||
{
|
{
|
||||||
// optimize: many cases, handler is single.
|
// 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;
|
bool isRunning;
|
||||||
IResolveCancelPromise<T> waitHandler;
|
ITriggerHandler<T> waitHandler;
|
||||||
MinimumQueue<IResolveCancelPromise<T>> waitQueue;
|
MinimumQueue<ITriggerHandler<T>> waitQueue;
|
||||||
|
|
||||||
public void SetResult(T value)
|
public void SetResult(T value)
|
||||||
{
|
{
|
||||||
|
@ -33,7 +32,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
singleHandler.TrySetResult(value);
|
singleHandler.OnNext(value);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -53,7 +52,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
handlers[i].TrySetResult(value);
|
handlers[i].OnNext(value);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -94,7 +93,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
((ICancelPromise)singleHandler).TrySetCanceled(cancellationToken);
|
(singleHandler).OnCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -114,7 +113,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
((ICancelPromise)handlers[i]).TrySetCanceled(cancellationToken);
|
(handlers[i]).OnCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
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)
|
if (isRunning)
|
||||||
{
|
{
|
||||||
|
@ -159,7 +219,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
if (waitQueue == null)
|
if (waitQueue == null)
|
||||||
{
|
{
|
||||||
waitQueue = new MinimumQueue<IResolveCancelPromise<T>>(4);
|
waitQueue = new MinimumQueue<ITriggerHandler<T>>(4);
|
||||||
}
|
}
|
||||||
waitQueue.Enqueue(handler);
|
waitQueue.Enqueue(handler);
|
||||||
return;
|
return;
|
||||||
|
@ -173,7 +233,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
if (handlers == null)
|
if (handlers == null)
|
||||||
{
|
{
|
||||||
handlers = new IResolveCancelPromise<T>[4];
|
handlers = new ITriggerHandler<T>[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
// check empty
|
// 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 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.Copy(array, 0, newArray, 0, array.Length);
|
||||||
array = newArray;
|
array = newArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(IResolveCancelPromise<T> handler)
|
public void Remove(ITriggerHandler<T> handler)
|
||||||
{
|
{
|
||||||
if (singleHandler == handler)
|
if (singleHandler == handler)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,10 +24,10 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
if (calledDestroy) return;
|
if (calledDestroy) return;
|
||||||
calledDestroy = true;
|
calledDestroy = true;
|
||||||
|
|
||||||
triggerEvent.SetCanceled(CancellationToken.None);
|
triggerEvent.SetCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddHandler(IResolveCancelPromise<T> handler)
|
internal void AddHandler(ITriggerHandler<T> handler)
|
||||||
{
|
{
|
||||||
if (!calledAwake)
|
if (!calledAwake)
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
triggerEvent.Add(handler);
|
triggerEvent.Add(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void RemoveHandler(IResolveCancelPromise<T> handler)
|
internal void RemoveHandler(ITriggerHandler<T> handler)
|
||||||
{
|
{
|
||||||
if (!calledAwake)
|
if (!calledAwake)
|
||||||
{
|
{
|
||||||
|
@ -57,7 +57,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
return new AsyncTriggerEnumerator(this, cancellationToken);
|
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;
|
static Action<object> cancellationCallback = CancellationCallback;
|
||||||
|
|
||||||
|
@ -73,15 +73,20 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
this.cancellationToken = cancellationToken;
|
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;
|
Current = value;
|
||||||
return completionSource.TrySetResult(true);
|
completionSource.TrySetResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted()
|
||||||
|
{
|
||||||
|
completionSource.TrySetResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CancellationCallback(object state)
|
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;
|
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)
|
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)]
|
[StructLayout(LayoutKind.Auto)]
|
||||||
public struct UniTaskCompletionSourceCore<TResult>
|
public struct UniTaskCompletionSourceCore<TResult>
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue