Add UniTask.WaitUntilCanceled

master
neuecc 2020-05-19 01:35:16 +09:00
parent fb1152d8f4
commit bbd5686816
3 changed files with 103 additions and 12 deletions

View File

@ -1,7 +1,4 @@
#if NET_4_6 || NET_STANDARD_2_0 || CSHARP_7_OR_LATER using System;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Cysharp.Threading.Tasks.Internal; using Cysharp.Threading.Tasks.Internal;
@ -21,7 +18,11 @@ namespace Cysharp.Threading.Tasks
public static IProgress<T> CreateOnlyValueChanged<T>(Action<T> handler, IEqualityComparer<T> comparer = null) public static IProgress<T> CreateOnlyValueChanged<T>(Action<T> handler, IEqualityComparer<T> comparer = null)
{ {
if (handler == null) return NullProgress<T>.Instance; if (handler == null) return NullProgress<T>.Instance;
#if UNITY_2018_3_OR_NEWER
return new OnlyValueChangedProgress<T>(handler, comparer ?? UnityEqualityComparer.GetDefault<T>()); return new OnlyValueChangedProgress<T>(handler, comparer ?? UnityEqualityComparer.GetDefault<T>());
#else
return new OnlyValueChangedProgress<T>(handler, comparer ?? EqualityComparer<T>.Default);
#endif
} }
sealed class NullProgress<T> : IProgress<T> sealed class NullProgress<T> : IProgress<T>
@ -83,6 +84,4 @@ namespace Cysharp.Threading.Tasks
} }
} }
} }
} }
#endif

View File

@ -19,6 +19,11 @@ namespace Cysharp.Threading.Tasks
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, out var token), token); return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, out var token), token);
} }
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update)
{
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, out var token), token);
}
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken)) public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken))
where T : class where T : class
{ {
@ -234,6 +239,91 @@ namespace Cysharp.Threading.Tasks
} }
} }
sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem
{
static readonly PromisePool<WaitUntilCanceledPromise> pool = new PromisePool<WaitUntilCanceledPromise>();
CancellationToken cancellationToken;
UniTaskCompletionSourceCore<object> core;
WaitUntilCanceledPromise()
{
}
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
}
var result = pool.TryRent() ?? new WaitUntilCanceledPromise();
result.cancellationToken = cancellationToken;
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
token = result.core.Version;
return result;
}
public void GetResult(short token)
{
try
{
TaskTracker.RemoveTracking(this);
core.GetResult(token);
}
finally
{
pool.TryReturn(this);
}
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public bool MoveNext()
{
if (cancellationToken.IsCancellationRequested)
{
core.TrySetResult(null);
return false;
}
return true;
}
public void Reset()
{
core.Reset();
cancellationToken = default;
}
~WaitUntilCanceledPromise()
{
if (pool.TryReturn(this))
{
GC.ReRegisterForFinalize(this);
}
}
}
// where T : UnityEngine.Object, can not add constraint // where T : UnityEngine.Object, can not add constraint
sealed class WaitUntilValueChangedUnityObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, IPromisePoolItem sealed class WaitUntilValueChangedUnityObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, IPromisePoolItem
{ {
@ -353,7 +443,6 @@ namespace Cysharp.Threading.Tasks
} }
} }
sealed class WaitUntilValueChangedStandardObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, IPromisePoolItem sealed class WaitUntilValueChangedStandardObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, IPromisePoolItem
where T : class where T : class
{ {

View File

@ -203,16 +203,19 @@ public class SandboxMain : MonoBehaviour
//await UniTaskAsyncEnumerable.EveryUpdate().Take(10).ForEachAsync((x, i) => rp.Value = i); //await UniTaskAsyncEnumerable.EveryUpdate().Take(10).ForEachAsync((x, i) => rp.Value = i);
//rp.Dispose(); //rp.Dispose();
var cts = new CancellationTokenSource();
Running(cts.Token).Forget();
await this.GetAsyncUpdateTrigger().ForEachAsync(x => Debug.Log("yeah"));
Debug.Log("DONE");
cts.CancelAfterSlim(TimeSpan.FromSeconds(3));
} }
async UniTaskVoid Running(IReadOnlyAsyncReactiveProperty<int> rp) async UniTaskVoid Running(CancellationToken ct)
{ {
Debug.Log("BEGIN"); Debug.Log("BEGIN");
await rp.ForEachAsync(x => Debug.Log("AR:" + x)); await UniTask.WaitUntilCanceled(ct);
Debug.Log("DONE"); Debug.Log("DONE");
} }