replace all promisepool to new taskpool system

master 2.0.12-rc9
neuecc 2020-05-29 03:43:18 +09:00
parent d5db96b913
commit 21bf08a6b3
19 changed files with 467 additions and 281 deletions

View File

@ -59,16 +59,22 @@ namespace Cysharp.Threading.Tasks
#if NETCOREAPP3_1 #if NETCOREAPP3_1
sealed class ThreadPoolWorkItem : IThreadPoolWorkItem sealed class ThreadPoolWorkItem : IThreadPoolWorkItem, ITaskPoolNode<ThreadPoolWorkItem>
{ {
static readonly ConcurrentQueue<ThreadPoolWorkItem> pool = new ConcurrentQueue<ThreadPoolWorkItem>(); static TaskPool<ThreadPoolWorkItem> pool;
public ThreadPoolWorkItem NextNode { get; set; }
static ThreadPoolWorkItem()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(ThreadPoolWorkItem), () => pool.Size);
}
Action continuation; Action continuation;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ThreadPoolWorkItem Create(Action continuation) public static ThreadPoolWorkItem Create(Action continuation)
{ {
if (!pool.TryDequeue(out var item)) if (!pool.TryPop(out var item))
{ {
item = new ThreadPoolWorkItem(); item = new ThreadPoolWorkItem();
} }
@ -82,9 +88,11 @@ namespace Cysharp.Threading.Tasks
{ {
var call = continuation; var call = continuation;
continuation = null; continuation = null;
pool.Enqueue(this); if (call != null)
{
call.Invoke(); pool.TryPush(this);
call.Invoke();
}
} }
} }

View File

@ -217,21 +217,23 @@ namespace NetCoreSandbox
ThreadPool.SetMinThreads(100, 100); ThreadPool.SetMinThreads(100, 100);
List<UniTask<int>> list = new List<UniTask<int>>(); //List<UniTask<int>> list = new List<UniTask<int>>();
for (int i = 0; i < 321; i++) for (int i = 0; i < short.MaxValue; i++)
{ {
list.Add(AsyncTest()); //// list.Add(AsyncTest());
await YieldCore();
} }
//await UniTask.WhenAll(list); //await UniTask.WhenAll(list);
Console.WriteLine("TOGO"); //Console.WriteLine("TOGO");
var a = await AsyncTest(); //var a = await AsyncTest();
var b = AsyncTest(); //var b = AsyncTest();
var c = AsyncTest(); //var c = AsyncTest();
await YieldCore();
await b; //await b;
await c; //await c;
foreach (var item in Cysharp.Threading.Tasks.Internal.TaskPoolMonitor.GetCacheSizeInfo()) foreach (var item in Cysharp.Threading.Tasks.Internal.TaskPoolMonitor.GetCacheSizeInfo())
@ -242,6 +244,11 @@ namespace NetCoreSandbox
Console.ReadLine(); Console.ReadLine();
} }
static async UniTask YieldCore()
{
await UniTask.Yield();
}
#pragma warning disable CS1998 #pragma warning disable CS1998

View File

@ -12,7 +12,6 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[StructLayout(LayoutKind.Auto)] [StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder public struct AsyncUniTaskMethodBuilder
{ {
// cache items.
internal IMoveNextRunnerPromise runnerPromise; internal IMoveNextRunnerPromise runnerPromise;
Exception ex; Exception ex;
@ -78,7 +77,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (runnerPromise == null) if (runnerPromise == null)
{ {
MoveNextRunnerPromise<TStateMachine>.SetStateMachine(ref this, ref stateMachine); AsyncUniTask<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runnerPromise.MoveNext); awaiter.OnCompleted(runnerPromise.MoveNext);
@ -93,7 +92,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (runnerPromise == null) if (runnerPromise == null)
{ {
MoveNextRunnerPromise<TStateMachine>.SetStateMachine(ref this, ref stateMachine); AsyncUniTask<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
} }
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext); awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
@ -134,7 +133,6 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[StructLayout(LayoutKind.Auto)] [StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder<T> public struct AsyncUniTaskMethodBuilder<T>
{ {
// cache items.
internal IMoveNextRunnerPromise<T> runnerPromise; internal IMoveNextRunnerPromise<T> runnerPromise;
Exception ex; Exception ex;
T result; T result;
@ -204,7 +202,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (runnerPromise == null) if (runnerPromise == null)
{ {
MoveNextRunnerPromise<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine); AsyncUniTask<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runnerPromise.MoveNext); awaiter.OnCompleted(runnerPromise.MoveNext);
@ -219,7 +217,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (runnerPromise == null) if (runnerPromise == null)
{ {
MoveNextRunnerPromise<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine); AsyncUniTask<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine);
} }
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext); awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);

View File

@ -4,10 +4,12 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security; using System.Security;
namespace Cysharp.Threading.Tasks.CompilerServices namespace Cysharp.Threading.Tasks.CompilerServices
{ {
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskVoidMethodBuilder public struct AsyncUniTaskVoidMethodBuilder
{ {
internal IMoveNextRunner runner; internal IMoveNextRunner runner;
@ -65,7 +67,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (runner == null) if (runner == null)
{ {
MoveNextRunner<TStateMachine>.SetStateMachine(ref this, ref stateMachine); AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runner.MoveNext); awaiter.OnCompleted(runner.MoveNext);
@ -80,7 +82,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (runner == null) if (runner == null)
{ {
MoveNextRunner<TStateMachine>.SetStateMachine(ref this, ref stateMachine); AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
} }
awaiter.UnsafeOnCompleted(runner.MoveNext); awaiter.UnsafeOnCompleted(runner.MoveNext);

View File

@ -29,16 +29,16 @@ namespace Cysharp.Threading.Tasks.CompilerServices
void SetException(Exception exception); void SetException(Exception exception);
} }
internal sealed class MoveNextRunner<TStateMachine> : IMoveNextRunner, ITaskPoolNode<MoveNextRunner<TStateMachine>> internal sealed class AsyncUniTaskVoid<TStateMachine> : IMoveNextRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
static TaskPool<MoveNextRunner<TStateMachine>> pool; static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
TStateMachine stateMachine; TStateMachine stateMachine;
public Action MoveNext { get; } public Action MoveNext { get; }
public MoveNextRunner() public AsyncUniTaskVoid()
{ {
MoveNext = Run; MoveNext = Run;
} }
@ -47,22 +47,24 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (!pool.TryPop(out var result)) if (!pool.TryPop(out var result))
{ {
result = new MoveNextRunner<TStateMachine>(); result = new AsyncUniTaskVoid<TStateMachine>();
} }
TaskTracker.TrackActiveTask(result, 3);
builder.runner = result; // set runner before copied. builder.runner = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build). result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
} }
static MoveNextRunner() static AsyncUniTaskVoid()
{ {
TaskPoolMonitor.RegisterSizeGettter(typeof(MoveNextRunner<TStateMachine>), () => pool.Size); TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncUniTaskVoid<TStateMachine>), () => pool.Size);
} }
public MoveNextRunner<TStateMachine> NextNode { get; set; } public AsyncUniTaskVoid<TStateMachine> NextNode { get; set; }
public void Return() public void Return()
{ {
TaskTracker.RemoveTracking(this);
stateMachine = default; stateMachine = default;
pool.TryPush(this); pool.TryPush(this);
} }
@ -73,12 +75,32 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
stateMachine.MoveNext(); 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<object> continuation, object state, short token)
{
}
void IUniTaskSource.GetResult(short token)
{
}
} }
internal class MoveNextRunnerPromise<TStateMachine> : IMoveNextRunnerPromise, IUniTaskSource, ITaskPoolNode<MoveNextRunnerPromise<TStateMachine>> internal sealed class AsyncUniTask<TStateMachine> : IMoveNextRunnerPromise, IUniTaskSource, ITaskPoolNode<AsyncUniTask<TStateMachine>>
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
static TaskPool<MoveNextRunnerPromise<TStateMachine>> pool; static TaskPool<AsyncUniTask<TStateMachine>> pool;
TStateMachine stateMachine; TStateMachine stateMachine;
@ -86,7 +108,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
UniTaskCompletionSourceCore<AsyncUnit> core; UniTaskCompletionSourceCore<AsyncUnit> core;
MoveNextRunnerPromise() AsyncUniTask()
{ {
MoveNext = Run; MoveNext = Run;
} }
@ -95,7 +117,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (!pool.TryPop(out var result)) if (!pool.TryPop(out var result))
{ {
result = new MoveNextRunnerPromise<TStateMachine>(); result = new AsyncUniTask<TStateMachine>();
} }
TaskTracker.TrackActiveTask(result, 3); TaskTracker.TrackActiveTask(result, 3);
@ -103,11 +125,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
result.stateMachine = stateMachine; // copy struct StateMachine(in release build). result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
} }
public MoveNextRunnerPromise<TStateMachine> NextNode { get; set; } public AsyncUniTask<TStateMachine> NextNode { get; set; }
static MoveNextRunnerPromise() static AsyncUniTask()
{ {
TaskPoolMonitor.RegisterSizeGettter(typeof(MoveNextRunnerPromise<TStateMachine>), () => pool.Size); TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine>), () => pool.Size);
} }
bool TryReturn() bool TryReturn()
@ -177,7 +199,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
core.OnCompleted(continuation, state, token); core.OnCompleted(continuation, state, token);
} }
~MoveNextRunnerPromise() ~AsyncUniTask()
{ {
if (TryReturn()) if (TryReturn())
{ {
@ -186,10 +208,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices
} }
} }
internal class MoveNextRunnerPromise<TStateMachine, T> : IMoveNextRunnerPromise<T>, IUniTaskSource<T>, ITaskPoolNode<MoveNextRunnerPromise<TStateMachine, T>> internal sealed class AsyncUniTask<TStateMachine, T> : IMoveNextRunnerPromise<T>, IUniTaskSource<T>, ITaskPoolNode<AsyncUniTask<TStateMachine, T>>
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
static TaskPool<MoveNextRunnerPromise<TStateMachine, T>> pool; static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
TStateMachine stateMachine; TStateMachine stateMachine;
@ -197,7 +219,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
UniTaskCompletionSourceCore<T> core; UniTaskCompletionSourceCore<T> core;
MoveNextRunnerPromise() AsyncUniTask()
{ {
MoveNext = Run; MoveNext = Run;
} }
@ -206,7 +228,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (!pool.TryPop(out var result)) if (!pool.TryPop(out var result))
{ {
result = new MoveNextRunnerPromise<TStateMachine, T>(); result = new AsyncUniTask<TStateMachine, T>();
} }
TaskTracker.TrackActiveTask(result, 3); TaskTracker.TrackActiveTask(result, 3);
@ -214,11 +236,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
result.stateMachine = stateMachine; // copy struct StateMachine(in release build). result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
} }
public MoveNextRunnerPromise<TStateMachine, T> NextNode { get; set; } public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
static MoveNextRunnerPromise() static AsyncUniTask()
{ {
TaskPoolMonitor.RegisterSizeGettter(typeof(MoveNextRunnerPromise<TStateMachine, T>), () => pool.Size); TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine, T>), () => pool.Size);
} }
bool TryReturn() bool TryReturn()
@ -294,7 +316,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
core.OnCompleted(continuation, state, token); core.OnCompleted(continuation, state, token);
} }
~MoveNextRunnerPromise() ~AsyncUniTask()
{ {
if (TryReturn()) if (TryReturn())
{ {

View File

@ -30,33 +30,14 @@ namespace Cysharp.Threading.Tasks
return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out var token), token); return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out var token), token);
} }
class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise> sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise>
{ {
static TaskPool<EnumeratorPromise> pool; static TaskPool<EnumeratorPromise> pool;
public EnumeratorPromise NextNode { get; set; } public EnumeratorPromise NextNode { get; set; }
static EnumeratorPromise() static EnumeratorPromise()
{ {
TaskPoolMonitor.RegisterSizeGettter(typeof(EnumeratorPromise), () => pool.Size); TaskPoolMonitor.RegisterSizeGetter(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);
} }
IEnumerator innerEnumerator; IEnumerator innerEnumerator;
@ -75,7 +56,11 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.innerEnumerator = ConsumeEnumerator(innerEnumerator);
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
@ -138,11 +123,13 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
innerEnumerator = default; innerEnumerator = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~EnumeratorPromise() ~EnumeratorPromise()

View File

@ -77,9 +77,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
{ {
static readonly PromisePool<AsyncOperationHandleConfiguredSource> pool = new PromisePool<AsyncOperationHandleConfiguredSource>(); static TaskPool<AsyncOperationHandleConfiguredSource> pool;
public AsyncOperationHandleConfiguredSource NextNode { get; set; }
static AsyncOperationHandleConfiguredSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
}
AsyncOperationHandle handle; AsyncOperationHandle handle;
IProgress<float> progress; IProgress<float> progress;
@ -99,7 +105,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.handle = handle;
result.progress = progress; result.progress = progress;
@ -117,12 +126,12 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -170,17 +179,19 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
core.Reset(); core.Reset();
TaskTracker.RemoveTracking(this);
handle = default; handle = default;
progress = default; progress = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~AsyncOperationHandleConfiguredSource() ~AsyncOperationHandleConfiguredSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
@ -254,9 +265,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, IPromisePoolItem sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
{ {
static readonly PromisePool<AsyncOperationHandleConfiguredSource<T>> pool = new PromisePool<AsyncOperationHandleConfiguredSource<T>>(); static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
public AsyncOperationHandleConfiguredSource<T> NextNode { get; set; }
static AsyncOperationHandleConfiguredSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
}
AsyncOperationHandle<T> handle; AsyncOperationHandle<T> handle;
IProgress<float> progress; IProgress<float> progress;
@ -276,7 +293,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new AsyncOperationHandleConfiguredSource<T>(); if (!pool.TryPop(out var result))
{
result = new AsyncOperationHandleConfiguredSource<T>();
}
result.handle = handle; result.handle = handle;
result.progress = progress; result.progress = progress;
@ -294,13 +314,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
return core.GetResult(token); return core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -353,17 +371,19 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
handle = default; handle = default;
progress = default; progress = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~AsyncOperationHandleConfiguredSource() ~AsyncOperationHandleConfiguredSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }

View File

@ -83,9 +83,16 @@ namespace Cysharp.Threading.Tasks
} }
} }
sealed class TweenConfiguredSource : IUniTaskSource, IPromisePoolItem sealed class TweenConfiguredSource : IUniTaskSource, ITaskPoolNode<TweenConfiguredSource>
{ {
static readonly PromisePool<TweenConfiguredSource> pool = new PromisePool<TweenConfiguredSource>(); static TaskPool<TweenConfiguredSource> pool;
public TweenConfiguredSource NextNode { get; set; }
static TweenConfiguredSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size);
}
static readonly Action<object> CancellationCallbackDelegate = CancellationCallback; static readonly Action<object> CancellationCallbackDelegate = CancellationCallback;
static readonly TweenCallback EmptyTweenCallback = () => { }; static readonly TweenCallback EmptyTweenCallback = () => { };
@ -111,7 +118,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.tween = tween;
result.cancelBehaviour = cancelBehaviour; result.cancelBehaviour = cancelBehaviour;
@ -194,12 +204,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -219,16 +228,18 @@ namespace Cysharp.Threading.Tasks
core.OnCompleted(continuation, state, token); core.OnCompleted(continuation, state, token);
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
tween = default; tween = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~TweenConfiguredSource() ~TweenConfiguredSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }

View File

@ -11,7 +11,7 @@ namespace Cysharp.Threading.Tasks.Internal
static PooledDelegate() static PooledDelegate()
{ {
TaskPoolMonitor.RegisterSizeGettter(typeof(PooledDelegate<T>), () => pool.Size); TaskPoolMonitor.RegisterSizeGetter(typeof(PooledDelegate<T>), () => pool.Size);
} }
readonly Action<T> runDelegate; readonly Action<T> runDelegate;

View File

@ -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<T>
where T : class, IPromisePoolItem
{
int count = 0;
readonly ConcurrentQueue<T> queue = new ConcurrentQueue<T>();
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;
}
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
namespace Cysharp.Threading.Tasks.Internal namespace Cysharp.Threading.Tasks.Internal
@ -44,6 +45,7 @@ namespace Cysharp.Threading.Tasks.Internal
} }
// mutable struct, don't mark readonly. // mutable struct, don't mark readonly.
[StructLayout(LayoutKind.Auto)]
public struct TaskPool<T> public struct TaskPool<T>
where T : class, ITaskPoolNode<T> where T : class, ITaskPoolNode<T>
{ {
@ -109,7 +111,7 @@ namespace Cysharp.Threading.Tasks.Internal
} }
} }
public static void RegisterSizeGettter(Type type, Func<int> getSize) public static void RegisterSizeGetter(Type type, Func<int> getSize)
{ {
sizes[type] = getSize; sizes[type] = getSize;
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Text;
using System.Threading; using System.Threading;
using Cysharp.Threading.Tasks.Internal; using Cysharp.Threading.Tasks.Internal;
@ -103,16 +104,11 @@ namespace Cysharp.Threading.Tasks
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
string typeName = null;
var keyType = listPool[i].Key.GetType(); var keyType = listPool[i].Key.GetType();
if (keyType.IsNested)
{ var sb = new StringBuilder();
typeName = keyType.DeclaringType.Name + "." + keyType.Name; TypeBeautify(keyType, sb);
} var typeName = sb.ToString();
else
{
typeName = keyType.Name;
}
action(listPool[i].Value.trackingId, typeName, listPool[i].Key.UnsafeGetStatus(), listPool[i].Value.addTime, listPool[i].Value.stackTrace); action(listPool[i].Value.trackingId, typeName, listPool[i].Key.UnsafeGetStatus(), listPool[i].Value.addTime, listPool[i].Value.stackTrace);
listPool[i] = new KeyValuePair<IUniTaskSource, (int trackingId, DateTime addTime, string stackTrace)>(null, (0, default(DateTime), null)); // clear listPool[i] = new KeyValuePair<IUniTaskSource, (int trackingId, DateTime addTime, string stackTrace)>(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);
}
}
} }
} }

View File

@ -56,9 +56,15 @@ namespace Cysharp.Threading.Tasks
: new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out token), token); : new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out token), token);
} }
sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<YieldPromise>
{ {
static readonly PromisePool<YieldPromise> pool = new PromisePool<YieldPromise>(); static TaskPool<YieldPromise> pool;
public YieldPromise NextNode { get; set; }
static YieldPromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(YieldPromise), () => pool.Size);
}
CancellationToken cancellationToken; CancellationToken cancellationToken;
UniTaskCompletionSourceCore<object> core; UniTaskCompletionSourceCore<object> core;
@ -74,7 +80,11 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new YieldPromise(); if (!pool.TryPop(out var result))
{
result = new YieldPromise();
}
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
@ -90,12 +100,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -126,24 +135,32 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~YieldPromise() ~YieldPromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
} }
} }
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
{ {
static readonly PromisePool<DelayFramePromise> pool = new PromisePool<DelayFramePromise>(); static TaskPool<DelayFramePromise> pool;
public DelayFramePromise NextNode { get; set; }
static DelayFramePromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(DelayFramePromise), () => pool.Size);
}
int delayFrameCount; int delayFrameCount;
CancellationToken cancellationToken; CancellationToken cancellationToken;
@ -162,7 +179,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.delayFrameCount = delayFrameCount;
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
@ -179,12 +199,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -221,26 +240,34 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
currentFrameCount = default; currentFrameCount = default;
delayFrameCount = default; delayFrameCount = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~DelayFramePromise() ~DelayFramePromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
} }
} }
sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayPromise>
{ {
static readonly PromisePool<DelayPromise> pool = new PromisePool<DelayPromise>(); static TaskPool<DelayPromise> pool;
public DelayPromise NextNode { get; set; }
static DelayPromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(DelayPromise), () => pool.Size);
}
float delayFrameTimeSpan; float delayFrameTimeSpan;
float elapsed; float elapsed;
@ -259,7 +286,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.elapsed = 0.0f;
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds; result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
@ -277,12 +307,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -319,26 +348,34 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
delayFrameTimeSpan = default; delayFrameTimeSpan = default;
elapsed = default; elapsed = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~DelayPromise() ~DelayPromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
} }
} }
sealed class DelayIgnoreTimeScalePromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem sealed class DelayIgnoreTimeScalePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayIgnoreTimeScalePromise>
{ {
static readonly PromisePool<DelayIgnoreTimeScalePromise> pool = new PromisePool<DelayIgnoreTimeScalePromise>(); static TaskPool<DelayIgnoreTimeScalePromise> pool;
public DelayIgnoreTimeScalePromise NextNode { get; set; }
static DelayIgnoreTimeScalePromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(DelayIgnoreTimeScalePromise), () => pool.Size);
}
float delayFrameTimeSpan; float delayFrameTimeSpan;
float elapsed; float elapsed;
@ -357,7 +394,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.elapsed = 0.0f;
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds; result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
@ -375,12 +415,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -417,17 +456,19 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
delayFrameTimeSpan = default; delayFrameTimeSpan = default;
elapsed = default; elapsed = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~DelayIgnoreTimeScalePromise() ~DelayIgnoreTimeScalePromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }

View File

@ -35,9 +35,15 @@ namespace Cysharp.Threading.Tasks
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out token), token); : WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out token), token);
} }
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
{ {
static readonly PromisePool<WaitUntilPromise> pool = new PromisePool<WaitUntilPromise>(); static TaskPool<WaitUntilPromise> pool;
public WaitUntilPromise NextNode { get; set; }
static WaitUntilPromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(WaitUntilPromise), () => pool.Size);
}
Func<bool> predicate; Func<bool> predicate;
CancellationToken cancellationToken; CancellationToken cancellationToken;
@ -55,7 +61,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.predicate = predicate;
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
@ -72,12 +81,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -121,25 +129,33 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
predicate = default; predicate = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~WaitUntilPromise() ~WaitUntilPromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
} }
} }
sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise>
{ {
static readonly PromisePool<WaitWhilePromise> pool = new PromisePool<WaitWhilePromise>(); static TaskPool<WaitWhilePromise> pool;
public WaitWhilePromise NextNode { get; set; }
static WaitWhilePromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(WaitWhilePromise), () => pool.Size);
}
Func<bool> predicate; Func<bool> predicate;
CancellationToken cancellationToken; CancellationToken cancellationToken;
@ -157,7 +173,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.predicate = predicate;
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
@ -174,12 +193,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -223,25 +241,33 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
predicate = default; predicate = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~WaitWhilePromise() ~WaitWhilePromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
} }
} }
sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilCanceledPromise>
{ {
static readonly PromisePool<WaitUntilCanceledPromise> pool = new PromisePool<WaitUntilCanceledPromise>(); static TaskPool<WaitUntilCanceledPromise> pool;
public WaitUntilCanceledPromise NextNode { get; set; }
static WaitUntilCanceledPromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(WaitUntilCanceledPromise), () => pool.Size);
}
CancellationToken cancellationToken; CancellationToken cancellationToken;
@ -258,7 +284,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new WaitUntilCanceledPromise(); if (!pool.TryPop(out var result))
{
result = new WaitUntilCanceledPromise();
}
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
@ -274,12 +303,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -309,15 +337,17 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~WaitUntilCanceledPromise() ~WaitUntilCanceledPromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
@ -325,9 +355,15 @@ namespace Cysharp.Threading.Tasks
} }
// 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, ITaskPoolNode<WaitUntilValueChangedUnityObjectPromise<T, U>>
{ {
static readonly PromisePool<WaitUntilValueChangedUnityObjectPromise<T, U>> pool = new PromisePool<WaitUntilValueChangedUnityObjectPromise<T, U>>(); static TaskPool<WaitUntilValueChangedUnityObjectPromise<T, U>> pool;
public WaitUntilValueChangedUnityObjectPromise<T, U> NextNode { get; set; }
static WaitUntilValueChangedUnityObjectPromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(WaitUntilValueChangedUnityObjectPromise<T, U>), () => pool.Size);
}
T target; T target;
UnityEngine.Object targetAsUnityObject; UnityEngine.Object targetAsUnityObject;
@ -349,7 +385,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource<U>.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource<U>.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new WaitUntilValueChangedUnityObjectPromise<T, U>(); if (!pool.TryPop(out var result))
{
result = new WaitUntilValueChangedUnityObjectPromise<T, U>();
}
result.target = target; result.target = target;
result.targetAsUnityObject = target as UnityEngine.Object; result.targetAsUnityObject = target as UnityEngine.Object;
@ -370,12 +409,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
return core.GetResult(token); return core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -426,29 +464,37 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
target = default; target = default;
currentValue = default; currentValue = default;
monitorFunction = default; monitorFunction = default;
equalityComparer = default; equalityComparer = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~WaitUntilValueChangedUnityObjectPromise() ~WaitUntilValueChangedUnityObjectPromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
} }
} }
sealed class WaitUntilValueChangedStandardObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, IPromisePoolItem sealed class WaitUntilValueChangedStandardObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, ITaskPoolNode<WaitUntilValueChangedStandardObjectPromise<T, U>>
where T : class where T : class
{ {
static readonly PromisePool<WaitUntilValueChangedStandardObjectPromise<T, U>> pool = new PromisePool<WaitUntilValueChangedStandardObjectPromise<T, U>>(); static TaskPool<WaitUntilValueChangedStandardObjectPromise<T, U>> pool;
public WaitUntilValueChangedStandardObjectPromise<T, U> NextNode { get; set; }
static WaitUntilValueChangedStandardObjectPromise()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(WaitUntilValueChangedStandardObjectPromise<T, U>), () => pool.Size);
}
WeakReference<T> target; WeakReference<T> target;
U currentValue; U currentValue;
@ -469,7 +515,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource<U>.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource<U>.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new WaitUntilValueChangedStandardObjectPromise<T, U>(); if (!pool.TryPop(out var result))
{
result = new WaitUntilValueChangedStandardObjectPromise<T, U>();
}
result.target = new WeakReference<T>(target, false); // wrap in WeakReference. result.target = new WeakReference<T>(target, false); // wrap in WeakReference.
result.monitorFunction = monitorFunction; result.monitorFunction = monitorFunction;
@ -489,12 +538,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
return core.GetResult(token); return core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -545,19 +593,21 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
target = default; target = default;
currentValue = default; currentValue = default;
monitorFunction = default; monitorFunction = default;
equalityComparer = default; equalityComparer = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~WaitUntilValueChangedStandardObjectPromise() ~WaitUntilValueChangedStandardObjectPromise()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }

View File

@ -375,9 +375,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
public class AutoResetUniTaskCompletionSource : IUniTaskSource, IPromisePoolItem, IPromise public class AutoResetUniTaskCompletionSource : IUniTaskSource, ITaskPoolNode<AutoResetUniTaskCompletionSource>, IPromise
{ {
static readonly PromisePool<AutoResetUniTaskCompletionSource> pool = new PromisePool<AutoResetUniTaskCompletionSource>(); static TaskPool<AutoResetUniTaskCompletionSource> pool;
public AutoResetUniTaskCompletionSource NextNode { get; set; }
static AutoResetUniTaskCompletionSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(AutoResetUniTaskCompletionSource), () => pool.Size);
}
UniTaskCompletionSourceCore<AsyncUnit> core; UniTaskCompletionSourceCore<AsyncUnit> core;
@ -388,9 +394,12 @@ namespace Cysharp.Threading.Tasks
[DebuggerHidden] [DebuggerHidden]
public static AutoResetUniTaskCompletionSource Create() public static AutoResetUniTaskCompletionSource Create()
{ {
var value = pool.TryRent() ?? new AutoResetUniTaskCompletionSource(); if (!pool.TryPop(out var result))
TaskTracker.TrackActiveTask(value, 2); {
return value; result = new AutoResetUniTaskCompletionSource();
}
TaskTracker.TrackActiveTask(result, 2);
return result;
} }
[DebuggerHidden] [DebuggerHidden]
@ -452,12 +461,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -481,14 +489,16 @@ namespace Cysharp.Threading.Tasks
} }
[DebuggerHidden] [DebuggerHidden]
void IPromisePoolItem.Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
return pool.TryPush(this);
} }
~AutoResetUniTaskCompletionSource() ~AutoResetUniTaskCompletionSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
return; return;
@ -591,9 +601,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
public class AutoResetUniTaskCompletionSource<T> : IUniTaskSource<T>, IPromisePoolItem, IPromise<T> public class AutoResetUniTaskCompletionSource<T> : IUniTaskSource<T>, ITaskPoolNode<AutoResetUniTaskCompletionSource<T>>, IPromise<T>
{ {
static readonly PromisePool<AutoResetUniTaskCompletionSource<T>> pool = new PromisePool<AutoResetUniTaskCompletionSource<T>>(); static TaskPool<AutoResetUniTaskCompletionSource<T>> pool;
public AutoResetUniTaskCompletionSource<T> NextNode { get; set; }
static AutoResetUniTaskCompletionSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(AutoResetUniTaskCompletionSource<T>), () => pool.Size);
}
UniTaskCompletionSourceCore<T> core; UniTaskCompletionSourceCore<T> core;
@ -604,7 +620,10 @@ namespace Cysharp.Threading.Tasks
[DebuggerHidden] [DebuggerHidden]
public static AutoResetUniTaskCompletionSource<T> Create() public static AutoResetUniTaskCompletionSource<T> Create()
{ {
var result = pool.TryRent() ?? new AutoResetUniTaskCompletionSource<T>(); if (!pool.TryPop(out var result))
{
result = new AutoResetUniTaskCompletionSource<T>();
}
TaskTracker.TrackActiveTask(result, 2); TaskTracker.TrackActiveTask(result, 2);
return result; return result;
} }
@ -668,12 +687,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
return core.GetResult(token); return core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -702,14 +720,17 @@ namespace Cysharp.Threading.Tasks
} }
[DebuggerHidden] [DebuggerHidden]
void IPromisePoolItem.Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
return pool.TryPush(this);
} }
~AutoResetUniTaskCompletionSource() ~AutoResetUniTaskCompletionSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }

View File

@ -571,7 +571,7 @@ namespace Cysharp.Threading.Tasks
#if UNITY_2018_3_OR_NEWER #if UNITY_2018_3_OR_NEWER
class ToCoroutineEnumerator : IEnumerator sealed class ToCoroutineEnumerator : IEnumerator
{ {
bool completed; bool completed;
UniTask task; UniTask task;
@ -629,12 +629,12 @@ namespace Cysharp.Threading.Tasks
return !completed; return !completed;
} }
public void Reset() void IEnumerator.Reset()
{ {
} }
} }
class ToCoroutineEnumerator<T> : IEnumerator sealed class ToCoroutineEnumerator<T> : IEnumerator
{ {
bool completed; bool completed;
Action<T> resultHandler = null; Action<T> resultHandler = null;
@ -700,11 +700,11 @@ namespace Cysharp.Threading.Tasks
return !completed; return !completed;
} }
public void Reset() void IEnumerator.Reset()
{ {
} }
} }
#endif #endif
} }
} }

View File

@ -75,9 +75,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
{ {
static readonly PromisePool<AsyncOperationConfiguredSource> pool = new PromisePool<AsyncOperationConfiguredSource>(); static TaskPool<AsyncOperationConfiguredSource> pool;
public AsyncOperationConfiguredSource NextNode { get; set; }
static AsyncOperationConfiguredSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(AsyncOperationConfiguredSource), () => pool.Size);
}
AsyncOperation asyncOperation; AsyncOperation asyncOperation;
IProgress<float> progress; IProgress<float> progress;
@ -97,7 +103,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); 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.asyncOperation = asyncOperation;
result.progress = progress; result.progress = progress;
@ -115,13 +124,12 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -162,17 +170,19 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
asyncOperation = default; asyncOperation = default;
progress = default; progress = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~AsyncOperationConfiguredSource() ~AsyncOperationConfiguredSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
@ -247,9 +257,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, IPromisePoolItem class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
{ {
static readonly PromisePool<ResourceRequestConfiguredSource> pool = new PromisePool<ResourceRequestConfiguredSource>(); static TaskPool<ResourceRequestConfiguredSource> pool;
public ResourceRequestConfiguredSource NextNode { get; set; }
static ResourceRequestConfiguredSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(ResourceRequestConfiguredSource), () => pool.Size);
}
ResourceRequest asyncOperation; ResourceRequest asyncOperation;
IProgress<float> progress; IProgress<float> progress;
@ -269,7 +285,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new ResourceRequestConfiguredSource(); if (!pool.TryPop(out var result))
{
result = new ResourceRequestConfiguredSource();
}
result.asyncOperation = asyncOperation; result.asyncOperation = asyncOperation;
result.progress = progress; result.progress = progress;
@ -287,13 +306,12 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
return core.GetResult(token); return core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -339,17 +357,19 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this);
core.Reset(); core.Reset();
asyncOperation = default; asyncOperation = default;
progress = default; progress = default;
cancellationToken = default; cancellationToken = default;
return pool.TryPush(this);
} }
~ResourceRequestConfiguredSource() ~ResourceRequestConfiguredSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
@ -424,9 +444,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, IPromisePoolItem class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
{ {
static readonly PromisePool<AssetBundleRequestConfiguredSource> pool = new PromisePool<AssetBundleRequestConfiguredSource>(); static TaskPool<AssetBundleRequestConfiguredSource> pool;
public AssetBundleRequestConfiguredSource NextNode { get; set; }
static AssetBundleRequestConfiguredSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(AssetBundleRequestConfiguredSource), () => pool.Size);
}
AssetBundleRequest asyncOperation; AssetBundleRequest asyncOperation;
IProgress<float> progress; IProgress<float> progress;
@ -446,7 +472,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new AssetBundleRequestConfiguredSource(); if (!pool.TryPop(out var result))
{
result = new AssetBundleRequestConfiguredSource();
}
result.asyncOperation = asyncOperation; result.asyncOperation = asyncOperation;
result.progress = progress; result.progress = progress;
@ -464,13 +493,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
return core.GetResult(token); return core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -516,17 +543,19 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
core.Reset(); core.Reset();
asyncOperation = default; asyncOperation = default;
progress = default; progress = default;
cancellationToken = default; cancellationToken = default;
TaskTracker.RemoveTracking(this);
return pool.TryPush(this);
} }
~AssetBundleRequestConfiguredSource() ~AssetBundleRequestConfiguredSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
@ -601,9 +630,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, IPromisePoolItem class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
{ {
static readonly PromisePool<AssetBundleCreateRequestConfiguredSource> pool = new PromisePool<AssetBundleCreateRequestConfiguredSource>(); static TaskPool<AssetBundleCreateRequestConfiguredSource> pool;
public AssetBundleCreateRequestConfiguredSource NextNode { get; set; }
static AssetBundleCreateRequestConfiguredSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(AssetBundleCreateRequestConfiguredSource), () => pool.Size);
}
AssetBundleCreateRequest asyncOperation; AssetBundleCreateRequest asyncOperation;
IProgress<float> progress; IProgress<float> progress;
@ -623,7 +658,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource<AssetBundle>.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource<AssetBundle>.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new AssetBundleCreateRequestConfiguredSource(); if (!pool.TryPop(out var result))
{
result = new AssetBundleCreateRequestConfiguredSource();
}
result.asyncOperation = asyncOperation; result.asyncOperation = asyncOperation;
result.progress = progress; result.progress = progress;
@ -641,13 +679,11 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
return core.GetResult(token); return core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -693,17 +729,19 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
core.Reset(); core.Reset();
asyncOperation = default; asyncOperation = default;
progress = default; progress = default;
cancellationToken = default; cancellationToken = default;
TaskTracker.RemoveTracking(this);
return pool.TryPush(this);
} }
~AssetBundleCreateRequestConfiguredSource() ~AssetBundleCreateRequestConfiguredSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }
@ -779,9 +817,15 @@ namespace Cysharp.Threading.Tasks
} }
} }
class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, IPromisePoolItem class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
{ {
static readonly PromisePool<UnityWebRequestAsyncOperationConfiguredSource> pool = new PromisePool<UnityWebRequestAsyncOperationConfiguredSource>(); static TaskPool<UnityWebRequestAsyncOperationConfiguredSource> pool;
public UnityWebRequestAsyncOperationConfiguredSource NextNode { get; set; }
static UnityWebRequestAsyncOperationConfiguredSource()
{
TaskPoolMonitor.RegisterSizeGetter(typeof(UnityWebRequestAsyncOperationConfiguredSource), () => pool.Size);
}
UnityWebRequestAsyncOperation asyncOperation; UnityWebRequestAsyncOperation asyncOperation;
IProgress<float> progress; IProgress<float> progress;
@ -801,7 +845,10 @@ namespace Cysharp.Threading.Tasks
return AutoResetUniTaskCompletionSource<UnityWebRequest>.CreateFromCanceled(cancellationToken, out token); return AutoResetUniTaskCompletionSource<UnityWebRequest>.CreateFromCanceled(cancellationToken, out token);
} }
var result = pool.TryRent() ?? new UnityWebRequestAsyncOperationConfiguredSource(); if (!pool.TryPop(out var result))
{
result = new UnityWebRequestAsyncOperationConfiguredSource();
}
result.asyncOperation = asyncOperation; result.asyncOperation = asyncOperation;
result.progress = progress; result.progress = progress;
@ -819,13 +866,12 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
TaskTracker.RemoveTracking(this);
return core.GetResult(token); return core.GetResult(token);
} }
finally finally
{ {
pool.TryReturn(this); TryReturn();
} }
} }
@ -872,17 +918,19 @@ namespace Cysharp.Threading.Tasks
return true; return true;
} }
public void Reset() bool TryReturn()
{ {
core.Reset(); core.Reset();
asyncOperation = default; asyncOperation = default;
progress = default; progress = default;
cancellationToken = default; cancellationToken = default;
TaskTracker.RemoveTracking(this);
return pool.TryPush(this);
} }
~UnityWebRequestAsyncOperationConfiguredSource() ~UnityWebRequestAsyncOperationConfiguredSource()
{ {
if (pool.TryReturn(this)) if (TryReturn())
{ {
GC.ReRegisterForFinalize(this); GC.ReRegisterForFinalize(this);
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "com.cysharp.unitask", "name": "com.cysharp.unitask",
"displayName": "UniTask", "displayName": "UniTask",
"version": "2.0.11-rc8", "version": "2.0.12-rc9",
"unity": "2019.1", "unity": "2019.1",
"description": "Provides an efficient async/await integration to Unity.", "description": "Provides an efficient async/await integration to Unity.",
"keywords": [ "async/await", "async", "Task", "UniTask" ], "keywords": [ "async/await", "async", "Task", "UniTask" ],

View File

@ -354,14 +354,17 @@ public class SandboxMain : MonoBehaviour
}).Forget(); }).Forget();
CloseAsync(this.GetCancellationTokenOnDestroy()).Forget();
okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield())); okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield()));
} }
async UniTaskVoid CloseAsync(CancellationToken cancellationToken = default) async UniTaskVoid CloseAsync(CancellationToken cancellationToken = default)
{ {
await UniTask.Yield(); while (true)
{
await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken);
}
} }
async UniTaskVoid Running(CancellationToken ct) async UniTaskVoid Running(CancellationToken ct)