diff --git a/src/UniTask.NetCore/NetCore/UniTask.Yield.cs b/src/UniTask.NetCore/NetCore/UniTask.Yield.cs index 5a147a6..77768a0 100644 --- a/src/UniTask.NetCore/NetCore/UniTask.Yield.cs +++ b/src/UniTask.NetCore/NetCore/UniTask.Yield.cs @@ -59,16 +59,22 @@ namespace Cysharp.Threading.Tasks #if NETCOREAPP3_1 - sealed class ThreadPoolWorkItem : IThreadPoolWorkItem + sealed class ThreadPoolWorkItem : IThreadPoolWorkItem, ITaskPoolNode { - static readonly ConcurrentQueue pool = new ConcurrentQueue(); + static TaskPool pool; + public ThreadPoolWorkItem NextNode { get; set; } + + static ThreadPoolWorkItem() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(ThreadPoolWorkItem), () => pool.Size); + } Action continuation; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ThreadPoolWorkItem Create(Action continuation) { - if (!pool.TryDequeue(out var item)) + if (!pool.TryPop(out var item)) { item = new ThreadPoolWorkItem(); } @@ -82,9 +88,11 @@ namespace Cysharp.Threading.Tasks { var call = continuation; continuation = null; - pool.Enqueue(this); - - call.Invoke(); + if (call != null) + { + pool.TryPush(this); + call.Invoke(); + } } } diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 2c6da20..ccc0966 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -217,21 +217,23 @@ namespace NetCoreSandbox ThreadPool.SetMinThreads(100, 100); - List> list = new List>(); - for (int i = 0; i < 321; i++) + //List> list = new List>(); + for (int i = 0; i < short.MaxValue; i++) { - list.Add(AsyncTest()); + //// list.Add(AsyncTest()); + await YieldCore(); } //await UniTask.WhenAll(list); - Console.WriteLine("TOGO"); + //Console.WriteLine("TOGO"); - var a = await AsyncTest(); - var b = AsyncTest(); - var c = AsyncTest(); + //var a = await AsyncTest(); + //var b = AsyncTest(); + //var c = AsyncTest(); + await YieldCore(); - await b; - await c; + //await b; + //await c; foreach (var item in Cysharp.Threading.Tasks.Internal.TaskPoolMonitor.GetCacheSizeInfo()) @@ -242,6 +244,11 @@ namespace NetCoreSandbox Console.ReadLine(); } + static async UniTask YieldCore() + { + await UniTask.Yield(); + } + #pragma warning disable CS1998 diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs index 7c4afcf..5f7b297 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs @@ -12,7 +12,6 @@ namespace Cysharp.Threading.Tasks.CompilerServices [StructLayout(LayoutKind.Auto)] public struct AsyncUniTaskMethodBuilder { - // cache items. internal IMoveNextRunnerPromise runnerPromise; Exception ex; @@ -78,7 +77,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (runnerPromise == null) { - MoveNextRunnerPromise.SetStateMachine(ref this, ref stateMachine); + AsyncUniTask.SetStateMachine(ref this, ref stateMachine); } awaiter.OnCompleted(runnerPromise.MoveNext); @@ -93,7 +92,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (runnerPromise == null) { - MoveNextRunnerPromise.SetStateMachine(ref this, ref stateMachine); + AsyncUniTask.SetStateMachine(ref this, ref stateMachine); } awaiter.UnsafeOnCompleted(runnerPromise.MoveNext); @@ -134,7 +133,6 @@ namespace Cysharp.Threading.Tasks.CompilerServices [StructLayout(LayoutKind.Auto)] public struct AsyncUniTaskMethodBuilder { - // cache items. internal IMoveNextRunnerPromise runnerPromise; Exception ex; T result; @@ -204,7 +202,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (runnerPromise == null) { - MoveNextRunnerPromise.SetStateMachine(ref this, ref stateMachine); + AsyncUniTask.SetStateMachine(ref this, ref stateMachine); } awaiter.OnCompleted(runnerPromise.MoveNext); @@ -219,7 +217,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (runnerPromise == null) { - MoveNextRunnerPromise.SetStateMachine(ref this, ref stateMachine); + AsyncUniTask.SetStateMachine(ref this, ref stateMachine); } awaiter.UnsafeOnCompleted(runnerPromise.MoveNext); diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs index 9c2e686..0e469d2 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs @@ -4,10 +4,12 @@ using System; using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Security; namespace Cysharp.Threading.Tasks.CompilerServices { + [StructLayout(LayoutKind.Auto)] public struct AsyncUniTaskVoidMethodBuilder { internal IMoveNextRunner runner; @@ -65,7 +67,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (runner == null) { - MoveNextRunner.SetStateMachine(ref this, ref stateMachine); + AsyncUniTaskVoid.SetStateMachine(ref this, ref stateMachine); } awaiter.OnCompleted(runner.MoveNext); @@ -80,7 +82,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (runner == null) { - MoveNextRunner.SetStateMachine(ref this, ref stateMachine); + AsyncUniTaskVoid.SetStateMachine(ref this, ref stateMachine); } awaiter.UnsafeOnCompleted(runner.MoveNext); diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/MoveNextRunner.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/MoveNextRunner.cs index 64ae8e1..78e4a51 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/MoveNextRunner.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/MoveNextRunner.cs @@ -29,16 +29,16 @@ namespace Cysharp.Threading.Tasks.CompilerServices void SetException(Exception exception); } - internal sealed class MoveNextRunner : IMoveNextRunner, ITaskPoolNode> + internal sealed class AsyncUniTaskVoid : IMoveNextRunner, ITaskPoolNode>, IUniTaskSource where TStateMachine : IAsyncStateMachine { - static TaskPool> pool; + static TaskPool> pool; TStateMachine stateMachine; public Action MoveNext { get; } - public MoveNextRunner() + public AsyncUniTaskVoid() { MoveNext = Run; } @@ -47,22 +47,24 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (!pool.TryPop(out var result)) { - result = new MoveNextRunner(); + result = new AsyncUniTaskVoid(); } + TaskTracker.TrackActiveTask(result, 3); builder.runner = result; // set runner before copied. result.stateMachine = stateMachine; // copy struct StateMachine(in release build). } - static MoveNextRunner() + static AsyncUniTaskVoid() { - TaskPoolMonitor.RegisterSizeGettter(typeof(MoveNextRunner), () => pool.Size); + TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncUniTaskVoid), () => pool.Size); } - public MoveNextRunner NextNode { get; set; } + public AsyncUniTaskVoid NextNode { get; set; } public void Return() { + TaskTracker.RemoveTracking(this); stateMachine = default; pool.TryPush(this); } @@ -73,12 +75,32 @@ namespace Cysharp.Threading.Tasks.CompilerServices { stateMachine.MoveNext(); } + + // dummy interface implementation for TaskTracker. + + UniTaskStatus IUniTaskSource.GetStatus(short token) + { + return UniTaskStatus.Pending; + } + + UniTaskStatus IUniTaskSource.UnsafeGetStatus() + { + return UniTaskStatus.Pending; + } + + void IUniTaskSource.OnCompleted(Action continuation, object state, short token) + { + } + + void IUniTaskSource.GetResult(short token) + { + } } - internal class MoveNextRunnerPromise : IMoveNextRunnerPromise, IUniTaskSource, ITaskPoolNode> + internal sealed class AsyncUniTask : IMoveNextRunnerPromise, IUniTaskSource, ITaskPoolNode> where TStateMachine : IAsyncStateMachine { - static TaskPool> pool; + static TaskPool> pool; TStateMachine stateMachine; @@ -86,7 +108,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices UniTaskCompletionSourceCore core; - MoveNextRunnerPromise() + AsyncUniTask() { MoveNext = Run; } @@ -95,7 +117,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (!pool.TryPop(out var result)) { - result = new MoveNextRunnerPromise(); + result = new AsyncUniTask(); } TaskTracker.TrackActiveTask(result, 3); @@ -103,11 +125,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices result.stateMachine = stateMachine; // copy struct StateMachine(in release build). } - public MoveNextRunnerPromise NextNode { get; set; } + public AsyncUniTask NextNode { get; set; } - static MoveNextRunnerPromise() + static AsyncUniTask() { - TaskPoolMonitor.RegisterSizeGettter(typeof(MoveNextRunnerPromise), () => pool.Size); + TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncUniTask), () => pool.Size); } bool TryReturn() @@ -177,7 +199,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices core.OnCompleted(continuation, state, token); } - ~MoveNextRunnerPromise() + ~AsyncUniTask() { if (TryReturn()) { @@ -186,10 +208,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices } } - internal class MoveNextRunnerPromise : IMoveNextRunnerPromise, IUniTaskSource, ITaskPoolNode> + internal sealed class AsyncUniTask : IMoveNextRunnerPromise, IUniTaskSource, ITaskPoolNode> where TStateMachine : IAsyncStateMachine { - static TaskPool> pool; + static TaskPool> pool; TStateMachine stateMachine; @@ -197,7 +219,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices UniTaskCompletionSourceCore core; - MoveNextRunnerPromise() + AsyncUniTask() { MoveNext = Run; } @@ -206,7 +228,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (!pool.TryPop(out var result)) { - result = new MoveNextRunnerPromise(); + result = new AsyncUniTask(); } TaskTracker.TrackActiveTask(result, 3); @@ -214,11 +236,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices result.stateMachine = stateMachine; // copy struct StateMachine(in release build). } - public MoveNextRunnerPromise NextNode { get; set; } + public AsyncUniTask NextNode { get; set; } - static MoveNextRunnerPromise() + static AsyncUniTask() { - TaskPoolMonitor.RegisterSizeGettter(typeof(MoveNextRunnerPromise), () => pool.Size); + TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncUniTask), () => pool.Size); } bool TryReturn() @@ -294,7 +316,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices core.OnCompleted(continuation, state, token); } - ~MoveNextRunnerPromise() + ~AsyncUniTask() { if (TryReturn()) { diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/EnumeratorAsyncExtensions.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/EnumeratorAsyncExtensions.cs index ac13142..e312519 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/EnumeratorAsyncExtensions.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/EnumeratorAsyncExtensions.cs @@ -30,33 +30,14 @@ namespace Cysharp.Threading.Tasks return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out var token), token); } - class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode + sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { static TaskPool pool; public EnumeratorPromise NextNode { get; set; } static EnumeratorPromise() { - TaskPoolMonitor.RegisterSizeGettter(typeof(EnumeratorPromise), () => pool.Size); - } - - static EnumeratorPromise Create() - { - if (!pool.TryPop(out var result)) - { - result = new EnumeratorPromise(); - } - TaskTracker.TrackActiveTask(result, 4); - return result; - } - - bool TryReturn() - { - TaskTracker.RemoveTracking(this); - core.Reset(); - innerEnumerator = default; - cancellationToken = default; - return pool.TryPush(this); + TaskPoolMonitor.RegisterSizeGetter(typeof(EnumeratorPromise), () => pool.Size); } IEnumerator innerEnumerator; @@ -75,7 +56,11 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = Create(); + if (!pool.TryPop(out var result)) + { + result = new EnumeratorPromise(); + } + TaskTracker.TrackActiveTask(result, 3); result.innerEnumerator = ConsumeEnumerator(innerEnumerator); result.cancellationToken = cancellationToken; @@ -138,11 +123,13 @@ namespace Cysharp.Threading.Tasks return false; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); innerEnumerator = default; cancellationToken = default; + return pool.TryPush(this); } ~EnumeratorPromise() diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/External/AddressableAsyncExtensions.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/External/AddressableAsyncExtensions.cs index 97aabeb..acfc101 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/External/AddressableAsyncExtensions.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/External/AddressableAsyncExtensions.cs @@ -77,9 +77,15 @@ namespace Cysharp.Threading.Tasks } } - sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public AsyncOperationHandleConfiguredSource NextNode { get; set; } + + static AsyncOperationHandleConfiguredSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size); + } AsyncOperationHandle handle; IProgress progress; @@ -99,7 +105,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new AsyncOperationHandleConfiguredSource(); + if (!pool.TryPop(out var result)) + { + result = new AsyncOperationHandleConfiguredSource(); + } result.handle = handle; result.progress = progress; @@ -117,12 +126,12 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); + core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -170,17 +179,19 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { core.Reset(); + TaskTracker.RemoveTracking(this); handle = default; progress = default; cancellationToken = default; + return pool.TryPush(this); } ~AsyncOperationHandleConfiguredSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } @@ -254,9 +265,15 @@ namespace Cysharp.Threading.Tasks } } - sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode> { - static readonly PromisePool> pool = new PromisePool>(); + static TaskPool> pool; + public AsyncOperationHandleConfiguredSource NextNode { get; set; } + + static AsyncOperationHandleConfiguredSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size); + } AsyncOperationHandle handle; IProgress progress; @@ -276,7 +293,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new AsyncOperationHandleConfiguredSource(); + if (!pool.TryPop(out var result)) + { + result = new AsyncOperationHandleConfiguredSource(); + } result.handle = handle; result.progress = progress; @@ -294,13 +314,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); - return core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -353,17 +371,19 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); handle = default; progress = default; cancellationToken = default; + return pool.TryPush(this); } ~AsyncOperationHandleConfiguredSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/External/DoTweenAsyncExtensions.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/External/DoTweenAsyncExtensions.cs index bca76a3..8813878 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/External/DoTweenAsyncExtensions.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/External/DoTweenAsyncExtensions.cs @@ -83,9 +83,16 @@ namespace Cysharp.Threading.Tasks } } - sealed class TweenConfiguredSource : IUniTaskSource, IPromisePoolItem + sealed class TweenConfiguredSource : IUniTaskSource, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public TweenConfiguredSource NextNode { get; set; } + + static TweenConfiguredSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size); + } + static readonly Action CancellationCallbackDelegate = CancellationCallback; static readonly TweenCallback EmptyTweenCallback = () => { }; @@ -111,7 +118,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new TweenConfiguredSource(); + if (!pool.TryPop(out var result)) + { + result = new TweenConfiguredSource(); + } result.tween = tween; result.cancelBehaviour = cancelBehaviour; @@ -194,12 +204,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -219,16 +228,18 @@ namespace Cysharp.Threading.Tasks core.OnCompleted(continuation, state, token); } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); tween = default; cancellationToken = default; + return pool.TryPush(this); } ~TweenConfiguredSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/PooledDelegate.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/PooledDelegate.cs index 7b12afc..56d08f5 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/PooledDelegate.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/PooledDelegate.cs @@ -11,7 +11,7 @@ namespace Cysharp.Threading.Tasks.Internal static PooledDelegate() { - TaskPoolMonitor.RegisterSizeGettter(typeof(PooledDelegate), () => pool.Size); + TaskPoolMonitor.RegisterSizeGetter(typeof(PooledDelegate), () => pool.Size); } readonly Action runDelegate; diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/PromisePool.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/PromisePool.cs deleted file mode 100644 index 83c3ada..0000000 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/PromisePool.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Collections.Concurrent; -using System.Runtime.CompilerServices; -using System.Threading; - -namespace Cysharp.Threading.Tasks.Internal -{ - // public, allow to user create custom operator with pool. - - public interface IPromisePoolItem - { - void Reset(); - } - - public class PromisePool - where T : class, IPromisePoolItem - { - int count = 0; - readonly ConcurrentQueue queue = new ConcurrentQueue(); - readonly int maxSize; - - public PromisePool(int maxSize = 256) - { - this.maxSize = maxSize; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public T TryRent() - { - if (queue.TryDequeue(out var value)) - { - Interlocked.Decrement(ref count); - return value; - } - - return null; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryReturn(T value) - { - value.Reset(); // reset when return. - - if (count < maxSize) - { - queue.Enqueue(value); - Interlocked.Increment(ref count); - return true; - } - else - { - return false; - } - } - } -} diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/TaskPool.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/TaskPool.cs index 2076bf0..f3be551 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/TaskPool.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/TaskPool.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; namespace Cysharp.Threading.Tasks.Internal @@ -44,6 +45,7 @@ namespace Cysharp.Threading.Tasks.Internal } // mutable struct, don't mark readonly. + [StructLayout(LayoutKind.Auto)] public struct TaskPool where T : class, ITaskPoolNode { @@ -109,7 +111,7 @@ namespace Cysharp.Threading.Tasks.Internal } } - public static void RegisterSizeGettter(Type type, Func getSize) + public static void RegisterSizeGetter(Type type, Func getSize) { sizes[type] = getSize; } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/TaskTracker.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/TaskTracker.cs index 18e1594..6627547 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/TaskTracker.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/TaskTracker.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Text; using System.Threading; using Cysharp.Threading.Tasks.Internal; @@ -103,16 +104,11 @@ namespace Cysharp.Threading.Tasks { for (int i = 0; i < count; i++) { - string typeName = null; var keyType = listPool[i].Key.GetType(); - if (keyType.IsNested) - { - typeName = keyType.DeclaringType.Name + "." + keyType.Name; - } - else - { - typeName = keyType.Name; - } + + var sb = new StringBuilder(); + TypeBeautify(keyType, sb); + var typeName = sb.ToString(); action(listPool[i].Value.trackingId, typeName, listPool[i].Key.UnsafeGetStatus(), listPool[i].Value.addTime, listPool[i].Value.stackTrace); listPool[i] = new KeyValuePair(null, (0, default(DateTime), null)); // clear @@ -125,6 +121,31 @@ namespace Cysharp.Threading.Tasks } } } + + static void TypeBeautify(Type type, StringBuilder sb) + { + if (type.IsNested) + { + TypeBeautify(type.DeclaringType, sb); + sb.Append("."); + } + + if (type.IsGenericType) + { + var genericsStart = type.Name.IndexOf("`"); + sb.Append(type.Name.Substring(0, genericsStart)); + sb.Append("<"); + foreach (var item in type.GetGenericArguments()) + { + TypeBeautify(item, sb); + } + sb.Append(">"); + } + else + { + sb.Append(type.Name); + } + } } } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Delay.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Delay.cs index 9951c1d..65b02fc 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Delay.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Delay.cs @@ -56,9 +56,15 @@ namespace Cysharp.Threading.Tasks : new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out token), token); } - sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public YieldPromise NextNode { get; set; } + + static YieldPromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(YieldPromise), () => pool.Size); + } CancellationToken cancellationToken; UniTaskCompletionSourceCore core; @@ -74,7 +80,11 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new YieldPromise(); + if (!pool.TryPop(out var result)) + { + result = new YieldPromise(); + } + result.cancellationToken = cancellationToken; @@ -90,12 +100,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -126,24 +135,32 @@ namespace Cysharp.Threading.Tasks return false; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); cancellationToken = default; + return pool.TryPush(this); } ~YieldPromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } } } - sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public DelayFramePromise NextNode { get; set; } + + static DelayFramePromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(DelayFramePromise), () => pool.Size); + } int delayFrameCount; CancellationToken cancellationToken; @@ -162,7 +179,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new DelayFramePromise(); + if (!pool.TryPop(out var result)) + { + result = new DelayFramePromise(); + } result.delayFrameCount = delayFrameCount; result.cancellationToken = cancellationToken; @@ -179,12 +199,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -221,26 +240,34 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); currentFrameCount = default; delayFrameCount = default; cancellationToken = default; + return pool.TryPush(this); } ~DelayFramePromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } } } - sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public DelayPromise NextNode { get; set; } + + static DelayPromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(DelayPromise), () => pool.Size); + } float delayFrameTimeSpan; float elapsed; @@ -259,7 +286,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new DelayPromise(); + if (!pool.TryPop(out var result)) + { + result = new DelayPromise(); + } result.elapsed = 0.0f; result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds; @@ -277,12 +307,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -319,26 +348,34 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); delayFrameTimeSpan = default; elapsed = default; cancellationToken = default; + return pool.TryPush(this); } ~DelayPromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } } } - sealed class DelayIgnoreTimeScalePromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class DelayIgnoreTimeScalePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public DelayIgnoreTimeScalePromise NextNode { get; set; } + + static DelayIgnoreTimeScalePromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(DelayIgnoreTimeScalePromise), () => pool.Size); + } float delayFrameTimeSpan; float elapsed; @@ -357,7 +394,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new DelayIgnoreTimeScalePromise(); + if (!pool.TryPop(out var result)) + { + result = new DelayIgnoreTimeScalePromise(); + } result.elapsed = 0.0f; result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds; @@ -375,12 +415,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -417,17 +456,19 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); delayFrameTimeSpan = default; elapsed = default; cancellationToken = default; + return pool.TryPush(this); } ~DelayIgnoreTimeScalePromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.WaitUntil.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.WaitUntil.cs index a4c67a2..ce58448 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.WaitUntil.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.WaitUntil.cs @@ -35,9 +35,15 @@ namespace Cysharp.Threading.Tasks : WaitUntilValueChangedStandardObjectPromise.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out token), token); } - sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public WaitUntilPromise NextNode { get; set; } + + static WaitUntilPromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(WaitUntilPromise), () => pool.Size); + } Func predicate; CancellationToken cancellationToken; @@ -55,7 +61,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new WaitUntilPromise(); + if (!pool.TryPop(out var result)) + { + result = new WaitUntilPromise(); + } result.predicate = predicate; result.cancellationToken = cancellationToken; @@ -72,12 +81,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -121,25 +129,33 @@ namespace Cysharp.Threading.Tasks return false; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); predicate = default; cancellationToken = default; + return pool.TryPush(this); } ~WaitUntilPromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } } } - sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public WaitWhilePromise NextNode { get; set; } + + static WaitWhilePromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(WaitWhilePromise), () => pool.Size); + } Func predicate; CancellationToken cancellationToken; @@ -157,7 +173,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new WaitWhilePromise(); + if (!pool.TryPop(out var result)) + { + result = new WaitWhilePromise(); + } result.predicate = predicate; result.cancellationToken = cancellationToken; @@ -174,12 +193,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -223,25 +241,33 @@ namespace Cysharp.Threading.Tasks return false; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); predicate = default; cancellationToken = default; + return pool.TryPush(this); } ~WaitWhilePromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } } } - sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public WaitUntilCanceledPromise NextNode { get; set; } + + static WaitUntilCanceledPromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(WaitUntilCanceledPromise), () => pool.Size); + } CancellationToken cancellationToken; @@ -258,7 +284,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new WaitUntilCanceledPromise(); + if (!pool.TryPop(out var result)) + { + result = new WaitUntilCanceledPromise(); + } result.cancellationToken = cancellationToken; @@ -274,12 +303,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -309,15 +337,17 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); cancellationToken = default; + return pool.TryPush(this); } ~WaitUntilCanceledPromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } @@ -325,9 +355,15 @@ namespace Cysharp.Threading.Tasks } // where T : UnityEngine.Object, can not add constraint - sealed class WaitUntilValueChangedUnityObjectPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class WaitUntilValueChangedUnityObjectPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode> { - static readonly PromisePool> pool = new PromisePool>(); + static TaskPool> pool; + public WaitUntilValueChangedUnityObjectPromise NextNode { get; set; } + + static WaitUntilValueChangedUnityObjectPromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(WaitUntilValueChangedUnityObjectPromise), () => pool.Size); + } T target; UnityEngine.Object targetAsUnityObject; @@ -349,7 +385,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new WaitUntilValueChangedUnityObjectPromise(); + if (!pool.TryPop(out var result)) + { + result = new WaitUntilValueChangedUnityObjectPromise(); + } result.target = target; result.targetAsUnityObject = target as UnityEngine.Object; @@ -370,12 +409,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); return core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -426,29 +464,37 @@ namespace Cysharp.Threading.Tasks return false; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); target = default; currentValue = default; monitorFunction = default; equalityComparer = default; cancellationToken = default; + return pool.TryPush(this); } ~WaitUntilValueChangedUnityObjectPromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } } } - sealed class WaitUntilValueChangedStandardObjectPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + sealed class WaitUntilValueChangedStandardObjectPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode> where T : class { - static readonly PromisePool> pool = new PromisePool>(); + static TaskPool> pool; + public WaitUntilValueChangedStandardObjectPromise NextNode { get; set; } + + static WaitUntilValueChangedStandardObjectPromise() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(WaitUntilValueChangedStandardObjectPromise), () => pool.Size); + } WeakReference target; U currentValue; @@ -469,7 +515,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new WaitUntilValueChangedStandardObjectPromise(); + if (!pool.TryPop(out var result)) + { + result = new WaitUntilValueChangedStandardObjectPromise(); + } result.target = new WeakReference(target, false); // wrap in WeakReference. result.monitorFunction = monitorFunction; @@ -489,12 +538,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); return core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -545,19 +593,21 @@ namespace Cysharp.Threading.Tasks return false; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); target = default; currentValue = default; monitorFunction = default; equalityComparer = default; cancellationToken = default; + return pool.TryPush(this); } ~WaitUntilValueChangedStandardObjectPromise() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskCompletionSource.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskCompletionSource.cs index 05d9339..93974b0 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskCompletionSource.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskCompletionSource.cs @@ -375,9 +375,15 @@ namespace Cysharp.Threading.Tasks } } - public class AutoResetUniTaskCompletionSource : IUniTaskSource, IPromisePoolItem, IPromise + public class AutoResetUniTaskCompletionSource : IUniTaskSource, ITaskPoolNode, IPromise { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public AutoResetUniTaskCompletionSource NextNode { get; set; } + + static AutoResetUniTaskCompletionSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(AutoResetUniTaskCompletionSource), () => pool.Size); + } UniTaskCompletionSourceCore core; @@ -388,9 +394,12 @@ namespace Cysharp.Threading.Tasks [DebuggerHidden] public static AutoResetUniTaskCompletionSource Create() { - var value = pool.TryRent() ?? new AutoResetUniTaskCompletionSource(); - TaskTracker.TrackActiveTask(value, 2); - return value; + if (!pool.TryPop(out var result)) + { + result = new AutoResetUniTaskCompletionSource(); + } + TaskTracker.TrackActiveTask(result, 2); + return result; } [DebuggerHidden] @@ -452,12 +461,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -481,14 +489,16 @@ namespace Cysharp.Threading.Tasks } [DebuggerHidden] - void IPromisePoolItem.Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); + return pool.TryPush(this); } ~AutoResetUniTaskCompletionSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); return; @@ -591,9 +601,15 @@ namespace Cysharp.Threading.Tasks } } - public class AutoResetUniTaskCompletionSource : IUniTaskSource, IPromisePoolItem, IPromise + public class AutoResetUniTaskCompletionSource : IUniTaskSource, ITaskPoolNode>, IPromise { - static readonly PromisePool> pool = new PromisePool>(); + static TaskPool> pool; + public AutoResetUniTaskCompletionSource NextNode { get; set; } + + static AutoResetUniTaskCompletionSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(AutoResetUniTaskCompletionSource), () => pool.Size); + } UniTaskCompletionSourceCore core; @@ -604,7 +620,10 @@ namespace Cysharp.Threading.Tasks [DebuggerHidden] public static AutoResetUniTaskCompletionSource Create() { - var result = pool.TryRent() ?? new AutoResetUniTaskCompletionSource(); + if (!pool.TryPop(out var result)) + { + result = new AutoResetUniTaskCompletionSource(); + } TaskTracker.TrackActiveTask(result, 2); return result; } @@ -668,12 +687,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); return core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -702,14 +720,17 @@ namespace Cysharp.Threading.Tasks } [DebuggerHidden] - void IPromisePoolItem.Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); + return pool.TryPush(this); } + ~AutoResetUniTaskCompletionSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskExtensions.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskExtensions.cs index 2c76ce1..cf31092 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskExtensions.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskExtensions.cs @@ -571,7 +571,7 @@ namespace Cysharp.Threading.Tasks #if UNITY_2018_3_OR_NEWER - class ToCoroutineEnumerator : IEnumerator + sealed class ToCoroutineEnumerator : IEnumerator { bool completed; UniTask task; @@ -629,12 +629,12 @@ namespace Cysharp.Threading.Tasks return !completed; } - public void Reset() + void IEnumerator.Reset() { } } - class ToCoroutineEnumerator : IEnumerator + sealed class ToCoroutineEnumerator : IEnumerator { bool completed; Action resultHandler = null; @@ -700,11 +700,11 @@ namespace Cysharp.Threading.Tasks return !completed; } - public void Reset() + void IEnumerator.Reset() { } } - + #endif } } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/UnityAsyncExtensions.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/UnityAsyncExtensions.cs index db1d7a2..05efb7c 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/UnityAsyncExtensions.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/UnityAsyncExtensions.cs @@ -75,9 +75,15 @@ namespace Cysharp.Threading.Tasks } } - class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public AsyncOperationConfiguredSource NextNode { get; set; } + + static AsyncOperationConfiguredSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncOperationConfiguredSource), () => pool.Size); + } AsyncOperation asyncOperation; IProgress progress; @@ -97,7 +103,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new AsyncOperationConfiguredSource(); + if (!pool.TryPop(out var result)) + { + result = new AsyncOperationConfiguredSource(); + } result.asyncOperation = asyncOperation; result.progress = progress; @@ -115,13 +124,12 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -162,17 +170,19 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); asyncOperation = default; progress = default; cancellationToken = default; + return pool.TryPush(this); } ~AsyncOperationConfiguredSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } @@ -247,9 +257,15 @@ namespace Cysharp.Threading.Tasks } } - class ResourceRequestConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + class ResourceRequestConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public ResourceRequestConfiguredSource NextNode { get; set; } + + static ResourceRequestConfiguredSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(ResourceRequestConfiguredSource), () => pool.Size); + } ResourceRequest asyncOperation; IProgress progress; @@ -269,7 +285,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new ResourceRequestConfiguredSource(); + if (!pool.TryPop(out var result)) + { + result = new ResourceRequestConfiguredSource(); + } result.asyncOperation = asyncOperation; result.progress = progress; @@ -287,13 +306,12 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); return core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -339,17 +357,19 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { + TaskTracker.RemoveTracking(this); core.Reset(); asyncOperation = default; progress = default; cancellationToken = default; + return pool.TryPush(this); } ~ResourceRequestConfiguredSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } @@ -424,9 +444,15 @@ namespace Cysharp.Threading.Tasks } } - class AssetBundleRequestConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + class AssetBundleRequestConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public AssetBundleRequestConfiguredSource NextNode { get; set; } + + static AssetBundleRequestConfiguredSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(AssetBundleRequestConfiguredSource), () => pool.Size); + } AssetBundleRequest asyncOperation; IProgress progress; @@ -446,7 +472,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new AssetBundleRequestConfiguredSource(); + if (!pool.TryPop(out var result)) + { + result = new AssetBundleRequestConfiguredSource(); + } result.asyncOperation = asyncOperation; result.progress = progress; @@ -464,13 +493,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); - return core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -516,17 +543,19 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { core.Reset(); asyncOperation = default; progress = default; cancellationToken = default; + TaskTracker.RemoveTracking(this); + return pool.TryPush(this); } ~AssetBundleRequestConfiguredSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } @@ -601,9 +630,15 @@ namespace Cysharp.Threading.Tasks } } - class AssetBundleCreateRequestConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + class AssetBundleCreateRequestConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public AssetBundleCreateRequestConfiguredSource NextNode { get; set; } + + static AssetBundleCreateRequestConfiguredSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(AssetBundleCreateRequestConfiguredSource), () => pool.Size); + } AssetBundleCreateRequest asyncOperation; IProgress progress; @@ -623,7 +658,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new AssetBundleCreateRequestConfiguredSource(); + if (!pool.TryPop(out var result)) + { + result = new AssetBundleCreateRequestConfiguredSource(); + } result.asyncOperation = asyncOperation; result.progress = progress; @@ -641,13 +679,11 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); - return core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -693,17 +729,19 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { core.Reset(); asyncOperation = default; progress = default; cancellationToken = default; + TaskTracker.RemoveTracking(this); + return pool.TryPush(this); } ~AssetBundleCreateRequestConfiguredSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } @@ -779,9 +817,15 @@ namespace Cysharp.Threading.Tasks } } - class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem + class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode { - static readonly PromisePool pool = new PromisePool(); + static TaskPool pool; + public UnityWebRequestAsyncOperationConfiguredSource NextNode { get; set; } + + static UnityWebRequestAsyncOperationConfiguredSource() + { + TaskPoolMonitor.RegisterSizeGetter(typeof(UnityWebRequestAsyncOperationConfiguredSource), () => pool.Size); + } UnityWebRequestAsyncOperation asyncOperation; IProgress progress; @@ -801,7 +845,10 @@ namespace Cysharp.Threading.Tasks return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } - var result = pool.TryRent() ?? new UnityWebRequestAsyncOperationConfiguredSource(); + if (!pool.TryPop(out var result)) + { + result = new UnityWebRequestAsyncOperationConfiguredSource(); + } result.asyncOperation = asyncOperation; result.progress = progress; @@ -819,13 +866,12 @@ namespace Cysharp.Threading.Tasks { try { - TaskTracker.RemoveTracking(this); return core.GetResult(token); } finally { - pool.TryReturn(this); + TryReturn(); } } @@ -872,17 +918,19 @@ namespace Cysharp.Threading.Tasks return true; } - public void Reset() + bool TryReturn() { core.Reset(); asyncOperation = default; progress = default; cancellationToken = default; + TaskTracker.RemoveTracking(this); + return pool.TryPush(this); } ~UnityWebRequestAsyncOperationConfiguredSource() { - if (pool.TryReturn(this)) + if (TryReturn()) { GC.ReRegisterForFinalize(this); } diff --git a/src/UniTask/Assets/Plugins/UniTask/package.json b/src/UniTask/Assets/Plugins/UniTask/package.json index 0857e58..36c9a90 100644 --- a/src/UniTask/Assets/Plugins/UniTask/package.json +++ b/src/UniTask/Assets/Plugins/UniTask/package.json @@ -1,7 +1,7 @@ { "name": "com.cysharp.unitask", "displayName": "UniTask", - "version": "2.0.11-rc8", + "version": "2.0.12-rc9", "unity": "2019.1", "description": "Provides an efficient async/await integration to Unity.", "keywords": [ "async/await", "async", "Task", "UniTask" ], diff --git a/src/UniTask/Assets/Scenes/SandboxMain.cs b/src/UniTask/Assets/Scenes/SandboxMain.cs index 39541b1..6953bf5 100644 --- a/src/UniTask/Assets/Scenes/SandboxMain.cs +++ b/src/UniTask/Assets/Scenes/SandboxMain.cs @@ -354,14 +354,17 @@ public class SandboxMain : MonoBehaviour }).Forget(); - + CloseAsync(this.GetCancellationTokenOnDestroy()).Forget(); okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield())); } async UniTaskVoid CloseAsync(CancellationToken cancellationToken = default) { - await UniTask.Yield(); + while (true) + { + await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken); + } } async UniTaskVoid Running(CancellationToken ct)