更新demo

更新demo
This commit is contained in:
ALEXTANG
2024-03-18 15:35:15 +08:00
parent 17a5d7425c
commit a2255b80cd
1028 changed files with 55353 additions and 35278 deletions

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 7f72c69c0975210489e927516c4494fc
guid: 275b87293edc6634f9d72387851dbbdf
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 40ef2e46f900131419e869398a8d3c9d
guid: e046ba353633f1e4b9552aa50e780fe0
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 52e2d973a2156674e8c1c9433ed031f7
guid: 1973dbb90ca25d94490075246d04549a
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 5bee3e3860e37484aa3b861bf76d129f
guid: 456b7e008397a8c4c81fac6abd52110a
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 967cc925e74341a408d1e0a0f611bc5e
guid: aa765154468d4b34eb34304100d39e64
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 07630c1e9fb2da542b4e0f6c6bd012db
guid: 64b064347ca7a404494a996b072e2e29
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 20067094c8a38b5428955c9e2e4285c7
guid: a3e874acee8398745b1dc3eddac09eaa
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: d93e9817915280849b2b41e93952452f
guid: a5b9231662e24c942b544bd85d4b39cb
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -25,7 +25,12 @@ namespace Cysharp.Threading.Tasks
return ToUniTask(handle, cancellationToken: cancellationToken);
}
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken, bool cancelImmediately)
{
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
@@ -44,7 +49,7 @@ namespace Cysharp.Threading.Tasks
return UniTask.CompletedTask;
}
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, out var token), token);
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
@@ -106,6 +111,7 @@ namespace Cysharp.Threading.Tasks
readonly Action<AsyncOperationHandle> continuationAction;
AsyncOperationHandle handle;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
IProgress<float> progress;
bool completed;
@@ -116,7 +122,7 @@ namespace Cysharp.Threading.Tasks
continuationAction = Continuation;
}
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -132,6 +138,15 @@ namespace Cysharp.Threading.Tasks
result.progress = progress;
result.cancellationToken = cancellationToken;
result.completed = false;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (AsyncOperationHandleConfiguredSource)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -219,6 +234,7 @@ namespace Cysharp.Threading.Tasks
handle = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -237,7 +253,12 @@ namespace Cysharp.Threading.Tasks
return ToUniTask(handle, cancellationToken: cancellationToken);
}
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken, bool cancelImmediately)
{
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
@@ -255,7 +276,7 @@ namespace Cysharp.Threading.Tasks
return UniTask.FromResult(handle.Result);
}
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, out var token), token);
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
@@ -272,6 +293,7 @@ namespace Cysharp.Threading.Tasks
readonly Action<AsyncOperationHandle<T>> continuationAction;
AsyncOperationHandle<T> handle;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
IProgress<float> progress;
bool completed;
@@ -282,7 +304,7 @@ namespace Cysharp.Threading.Tasks
continuationAction = Continuation;
}
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -298,6 +320,15 @@ namespace Cysharp.Threading.Tasks
result.cancellationToken = cancellationToken;
result.completed = false;
result.progress = progress;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (AsyncOperationHandleConfiguredSource<T>)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -390,6 +421,7 @@ namespace Cysharp.Threading.Tasks
handle = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: e9001e9737c47974ba2a210d33589248
guid: d96696960b382384190300495cd26735
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -148,6 +148,7 @@ namespace Cysharp.Threading.Tasks
Tween tween;
TweenCancelBehaviour cancelBehaviour;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationRegistration;
CallbackType callbackType;
bool canceled;
@@ -207,7 +208,7 @@ namespace Cysharp.Threading.Tasks
default:
break;
}
if (result.originalCompleteAction == result.onCompleteCallbackDelegate)
{
result.originalCompleteAction = null;
@@ -215,7 +216,7 @@ namespace Cysharp.Threading.Tasks
if (cancellationToken.CanBeCanceled)
{
cancellationToken.RegisterWithoutCaptureExecutionContext(x =>
result.cancellationRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(x =>
{
var source = (TweenConfiguredSource)x;
switch (source.cancelBehaviour)
@@ -250,30 +251,7 @@ namespace Cysharp.Threading.Tasks
source.tween.Complete(true);
break;
case TweenCancelBehaviour.CancelAwait:
// restore to original callback
switch (callbackType)
{
case CallbackType.Kill:
tween.onKill = source.originalCompleteAction;
break;
case CallbackType.Complete:
tween.onComplete = source.originalCompleteAction;
break;
case CallbackType.Pause:
tween.onPause = source.originalCompleteAction;
break;
case CallbackType.Play:
tween.onPlay = source.originalCompleteAction;
break;
case CallbackType.Rewind:
tween.onRewind = source.originalCompleteAction;
break;
case CallbackType.StepComplete:
tween.onStepComplete = source.originalCompleteAction;
break;
default:
break;
}
source.RestoreOriginalCallback();
source.core.TrySetCanceled(source.cancellationToken);
break;
}
@@ -376,7 +354,18 @@ namespace Cysharp.Threading.Tasks
{
TaskTracker.RemoveTracking(this);
core.Reset();
cancellationRegistration.Dispose();
RestoreOriginalCallback();
tween = default;
cancellationToken = default;
originalCompleteAction = default;
return pool.TryPush(this);
}
void RestoreOriginalCallback()
{
switch (callbackType)
{
case CallbackType.Kill:
@@ -400,11 +389,6 @@ namespace Cysharp.Threading.Tasks
default:
break;
}
tween = default;
cancellationToken = default;
originalCompleteAction = default;
return pool.TryPush(this);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1f448d5bc5b232e4f98d89d5d1832e8e
guid: c517968e1258cb649984dddf2c0ad8b0
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 029c1c1b674aaae47a6841a0b89ad80e
guid: a40cecb731a38b340b0d3899da286566
AssemblyDefinitionImporter:
externalObjects: {}
userData:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c1b167ace675fd04898df969ebbbd5bb
guid: 3cc67eb6c366477469fdf07a6922c183
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 79f4f2475e0b2c44e97ed1dee760627b
guid: 930414e3dd7d9d746a13c3a0f14ba5e7
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,66 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var handlers = new (string name, string type)[] {
("ValueChanged", "string"),
("EndEdit", "string"),
("EndTextSelection", "(string, int, int)"),
("TextSelection", "(string, int, int)"),
("Deselect", "string"),
("Select", "string"),
("Submit", "string"),
};
Func<string, bool> shouldConvert = x => x.EndsWith("TextSelection");
Func<string, string> eventName = x => shouldConvert(x) ? $"new TextSelectionEventConverter(inputField.on{x})" : $"inputField.on{x}";
#>
#if UNITASK_TEXTMESHPRO_SUPPORT
using System;
using System.Threading;
using TMPro;
namespace Cysharp.Threading.Tasks
{
public static partial class TextMeshProAsyncExtensions
{
<# foreach(var (name, type) in handlers) { #>
public static IAsync<#= (name) #>EventHandler<<#= type #>> GetAsync<#= (name) #>EventHandler(this TMP_InputField inputField)
{
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy(), false);
}
public static IAsync<#= (name) #>EventHandler<<#= type #>> GetAsync<#= (name) #>EventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
{
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, cancellationToken, false);
}
public static UniTask<<#= type #>> On<#= (name) #>Async(this TMP_InputField inputField)
{
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
}
public static UniTask<<#= type #>> On<#= (name) #>Async(this TMP_InputField inputField, CancellationToken cancellationToken)
{
return new AsyncUnityEventHandler<<#= type #>>(<#= eventName(name) #>, cancellationToken, true).OnInvokeAsync();
}
public static IUniTaskAsyncEnumerable<<#= type #>> On<#= (name) #>AsAsyncEnumerable(this TMP_InputField inputField)
{
return new UnityEventHandlerAsyncEnumerable<<#= type #>>(<#= eventName(name) #>, inputField.GetCancellationTokenOnDestroy());
}
public static IUniTaskAsyncEnumerable<<#= type #>> On<#= (name) #>AsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
{
return new UnityEventHandlerAsyncEnumerable<<#= type #>>(<#= eventName(name) #>, cancellationToken);
}
<# } #>
}
}
#endif

View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: 2b91a2c0e3055f54a8aab905c4163009
AssemblyDefinitionImporter:
guid: 9a4a4017ce5c23445a882e87e8cb103c
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: b6ba480edafb67d4e91bb10feb64fae5
guid: a9cba699cacf633438f41c07916c83d0
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: dc47925d1a5fa2946bdd37746b2b5d48
guid: d82b75b6a37050140bd967e8499035d8
AssemblyDefinitionImporter:
externalObjects: {}
userData:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6ba497ad9fe06174ea0e46a2b9b61ff5
guid: 8a55ef7d1bba14cc982b478d482c4461
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,79 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Runtime.CompilerServices;
namespace Cysharp.Threading.Tasks.Internal
{
internal static class Error
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ThrowArgumentNullException<T>(T value, string paramName)
where T : class
{
if (value == null) ThrowArgumentNullExceptionCore(paramName);
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void ThrowArgumentNullExceptionCore(string paramName)
{
throw new ArgumentNullException(paramName);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Exception ArgumentOutOfRange(string paramName)
{
return new ArgumentOutOfRangeException(paramName);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Exception NoElements()
{
return new InvalidOperationException("Source sequence doesn't contain any elements.");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Exception MoreThanOneElement()
{
return new InvalidOperationException("Source sequence contains more than one element.");
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowArgumentException(string message)
{
throw new ArgumentException(message);
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowNotYetCompleted()
{
throw new InvalidOperationException("Not yet completed.");
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static T ThrowNotYetCompleted<T>()
{
throw new InvalidOperationException("Not yet completed.");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ThrowWhenContinuationIsAlreadyRegistered<T>(T continuationField)
where T : class
{
if (continuationField != null) ThrowInvalidOperationExceptionCore("continuation is already registered.");
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void ThrowInvalidOperationExceptionCore(string message)
{
throw new InvalidOperationException(message);
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowOperationCanceledException()
{
throw new OperationCanceledException();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 4cd4f29f0b944572a9ddaeb813494a03
timeCreated: 1694767045

View File

@@ -12,12 +12,12 @@ namespace Cysharp.Threading.Tasks
{
public static class OperationHandleBaseExtensions
{
public static UniTask.Awaiter GetAwaiter(this OperationHandleBase handle)
public static UniTask.Awaiter GetAwaiter(this HandleBase handle)
{
return ToUniTask(handle).GetAwaiter();
}
public static UniTask ToUniTask(this OperationHandleBase handle,
public static UniTask ToUniTask(this HandleBase handle,
IProgress<float> progress = null,
PlayerLoopTiming timing = PlayerLoopTiming.Update)
{
@@ -54,15 +54,15 @@ namespace Cysharp.Threading.Tasks
TaskPool.RegisterSizeGetter(typeof(OperationHandleBaserConfiguredSource), () => pool.Size);
}
private readonly Action<OperationHandleBase> continuationAction;
private OperationHandleBase handle;
private readonly Action<HandleBase> continuationAction;
private HandleBase handle;
private IProgress<float> progress;
private bool completed;
private UniTaskCompletionSourceCore<AsyncUnit> core;
OperationHandleBaserConfiguredSource() { continuationAction = Continuation; }
public static IUniTaskSource Create(OperationHandleBase handle,
public static IUniTaskSource Create(HandleBase handle,
PlayerLoopTiming timing,
IProgress<float> progress,
out short token)
@@ -83,40 +83,46 @@ namespace Cysharp.Threading.Tasks
}
// BUG 在 Unity 2020.3.36 版本测试中, IL2Cpp 会报 如下错误
// BUG ArgumentException: Incompatible Delegate Types. First is System.Action`1[[YooAsset.AssetOperationHandle, YooAsset, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]] second is System.Action`1[[YooAsset.OperationHandleBase, YooAsset, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]
// BUG ArgumentException: Incompatible Delegate Types. First is System.Action`1[[YooAsset.AssetHandle, YooAsset, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]] second is System.Action`1[[YooAsset.OperationHandleBase, YooAsset, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]
// BUG 也可能报的是 Action '1' Action '1' 的 InvalidCastException
// BUG 此处不得不这么修改, 如果后续 Unity 修复了这个问题, 可以恢复之前的写法
#if UNITY_2020_BUG
switch(handle)
{
case AssetOperationHandle asset_handle:
case AssetHandle asset_handle:
asset_handle.Completed += result.AssetContinuation;
break;
case SceneOperationHandle scene_handle:
case SceneHandle scene_handle:
scene_handle.Completed += result.SceneContinuation;
break;
case SubAssetsOperationHandle sub_asset_handle:
case SubAssetsHandle sub_asset_handle:
sub_asset_handle.Completed += result.SubContinuation;
break;
case RawFileOperationHandle raw_file_handle:
case RawFileHandle raw_file_handle:
raw_file_handle.Completed += result.RawFileContinuation;
break;
case AllAssetsHandle all_assets_handle:
all_assets_handle.Completed += result.AllAssetsContinuation;
break;
}
#else
switch (handle)
{
case AssetOperationHandle asset_handle:
case AssetHandle asset_handle:
asset_handle.Completed += result.continuationAction;
break;
case SceneOperationHandle scene_handle:
case SceneHandle scene_handle:
scene_handle.Completed += result.continuationAction;
break;
case SubAssetsOperationHandle sub_asset_handle:
case SubAssetsHandle sub_asset_handle:
sub_asset_handle.Completed += result.continuationAction;
break;
case RawFileOperationHandle raw_file_handle:
case RawFileHandle raw_file_handle:
raw_file_handle.Completed += result.continuationAction;
break;
case AllAssetsHandle all_assets_handle:
all_assets_handle.Completed += result.continuationAction;
break;
}
#endif
token = result.core.Version;
@@ -124,29 +130,35 @@ namespace Cysharp.Threading.Tasks
return result;
}
#if UNITY_2020_BUG
private void AssetContinuation(AssetOperationHandle handle)
private void AssetContinuation(AssetHandle handle)
{
handle.Completed -= AssetContinuation;
BaseContinuation();
}
private void SceneContinuation(SceneOperationHandle handle)
private void SceneContinuation(SceneHandle handle)
{
handle.Completed -= SceneContinuation;
BaseContinuation();
}
private void SubContinuation(SubAssetsOperationHandle handle)
private void SubContinuation(SubAssetsHandle handle)
{
handle.Completed -= SubContinuation;
BaseContinuation();
}
private void RawFileContinuation(RawFileOperationHandle handle)
private void RawFileContinuation(RawFileHandle handle)
{
handle.Completed -= RawFileContinuation;
BaseContinuation();
}
private void AllAssetsContinuation(AllAssetsHandle handle)
{
handle.Completed -= AllAssetsContinuation;
BaseContinuation();
}
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void BaseContinuation()
@@ -169,22 +181,25 @@ namespace Cysharp.Threading.Tasks
}
}
private void Continuation(OperationHandleBase _)
private void Continuation(HandleBase _)
{
switch(handle)
{
case AssetOperationHandle asset_handle:
case AssetHandle asset_handle:
asset_handle.Completed -= continuationAction;
break;
case SceneOperationHandle scene_handle:
case SceneHandle scene_handle:
scene_handle.Completed -= continuationAction;
break;
case SubAssetsOperationHandle sub_asset_handle:
case SubAssetsHandle sub_asset_handle:
sub_asset_handle.Completed -= continuationAction;
break;
case RawFileOperationHandle raw_file_handle:
case RawFileHandle raw_file_handle:
raw_file_handle.Completed -= continuationAction;
break;
case AllAssetsHandle all_assets_handle:
all_assets_handle.Completed -= continuationAction;
break;
}
BaseContinuation();

View File

@@ -1,17 +0,0 @@
{
"name": "UniTask.YooAsset",
"rootNamespace": "",
"references": [
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:e34a5702dd353724aa315fb8011f08c3"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 2e72e370b27cbfd41af43a5e7ecce552
guid: 633f49a8aafb6fa43894cd4646c71743
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 87f9c2230fa75e241ad00d0082d4bdf2
guid: 4cc94a232b1c1154b8084bdda29c3484
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,237 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var types = new[]
{
(typeof(int), "double"),
(typeof(long), "double"),
(typeof(float),"float"),
(typeof(double),"double"),
(typeof(decimal),"decimal"),
(typeof(int?),"double?"),
(typeof(long?),"double?"),
(typeof(float?),"float?"),
(typeof(double?),"double?"),
(typeof(decimal?),"decimal?"),
};
Func<Type, bool> IsNullable = x => x.IsGenericType;
Func<Type, Type> ElementType = x => IsNullable(x) ? x.GetGenericArguments()[0] : x;
Func<Type, string> TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name;
Func<Type, string> WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : "";
Func<Type, string> CalcResult = x => { var e = ElementType(x); return (e == typeof(int) || e == typeof(long)) ? "(double)sum / count" : (e == typeof(float)) ? "(float)(sum / count)" : "sum / count"; };
#>
using System;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
<# foreach(var (t, ret) in types) { #>
public static UniTask<<#= ret #>> AverageAsync(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Average.AverageAsync(source, cancellationToken);
}
public static UniTask<<#= ret #>> AverageAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Average.AverageAsync(source, selector, cancellationToken);
}
public static UniTask<<#= ret #>> AverageAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Average.AverageAwaitAsync(source, selector, cancellationToken);
}
public static UniTask<<#= ret #>> AverageAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Average.AverageAwaitWithCancellationAsync(source, selector, cancellationToken);
}
<# } #>
}
internal static class Average
{
<# foreach(var (t, ret) in types) { #>
public static async UniTask<<#= ret #>> AverageAsync(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken)
{
long count = 0;
<#= TypeName(t) #> sum = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
<# if (IsNullable(t)) { #>
var v = e.Current;
if (v.HasValue)
{
checked
{
sum += v.Value;
count++;
}
}
<# } else { #>
checked
{
sum += e.Current;
count++;
}
<# } #>
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return <#= CalcResult(t) #>;
}
public static async UniTask<<#= ret #>> AverageAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken)
{
long count = 0;
<#= TypeName(t) #> sum = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
<# if (IsNullable(t)) { #>
var v = selector(e.Current);
if (v.HasValue)
{
checked
{
sum += v.Value;
count++;
}
}
<# } else { #>
checked
{
sum += selector(e.Current);
count++;
}
<# } #>
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return <#= CalcResult(t) #>;
}
public static async UniTask<<#= ret #>> AverageAwaitAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
long count = 0;
<#= TypeName(t) #> sum = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
<# if (IsNullable(t)) { #>
var v = await selector(e.Current);
if (v.HasValue)
{
checked
{
sum += v.Value;
count++;
}
}
<# } else { #>
checked
{
sum += await selector(e.Current);
count++;
}
<# } #>
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return <#= CalcResult(t) #>;
}
public static async UniTask<<#= ret #>> AverageAwaitWithCancellationAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
long count = 0;
<#= TypeName(t) #> sum = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
<# if (IsNullable(t)) { #>
var v = await selector(e.Current, cancellationToken);
if (v.HasValue)
{
checked
{
sum += v.Value;
count++;
}
}
<# } else { #>
checked
{
sum += await selector(e.Current, cancellationToken);
count++;
}
<# } #>
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return <#= CalcResult(t) #>;
}
<# } #>
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 84bce45768c171d4490153eb08630a98
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,221 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var tMax = 15;
Func<int, string> typeArgs = x => string.Join(", ", Enumerable.Range(1, x).Select(x => $"T{x}")) + ", TResult";
Func<int, string> paramArgs = x => string.Join(", ", Enumerable.Range(1, x).Select(x => $"IUniTaskAsyncEnumerable<T{x}> source{x}"));
Func<int, string> parameters = x => string.Join(", ", Enumerable.Range(1, x).Select(x => $"source{x}"));
#>
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
<# for(var i = 2; i <= tMax; i++) { #>
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<<#= typeArgs(i) #>>(this <#= paramArgs(i) #>, Func<<#= typeArgs(i) #>> resultSelector)
{
<# for(var j = 1; j <= i; j++) { #>
Error.ThrowArgumentNullException(source<#= j #>, nameof(source<#= j #>));
<# } #>
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new CombineLatest<<#= typeArgs(i) #>>(<#= parameters(i) #>, resultSelector);
}
<# } #>
}
<# for(var i = 2; i <= tMax; i++) { #>
internal class CombineLatest<<#= typeArgs(i) #>> : IUniTaskAsyncEnumerable<TResult>
{
<# for(var j = 1; j <= i; j++) { #>
readonly IUniTaskAsyncEnumerable<T<#= j #>> source<#= j #>;
<# } #>
readonly Func<<#= typeArgs(i) #>> resultSelector;
public CombineLatest(<#= paramArgs(i) #>, Func<<#= typeArgs(i) #>> resultSelector)
{
<# for(var j = 1; j <= i; j++) { #>
this.source<#= j #> = source<#= j #>;
<# } #>
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new _CombineLatest(<#= parameters(i) #>, resultSelector, cancellationToken);
}
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
<# for(var j = 1; j <= i; j++) { #>
static readonly Action<object> Completed<#= j #>Delegate = Completed<#= j #>;
<# } #>
const int CompleteCount = <#= i #>;
<# for(var j = 1; j <= i; j++) { #>
readonly IUniTaskAsyncEnumerable<T<#= j #>> source<#= j #>;
<# } #>
readonly Func<<#= typeArgs(i) #>> resultSelector;
CancellationToken cancellationToken;
<# for(var j = 1; j <= i; j++) { #>
IUniTaskAsyncEnumerator<T<#= j #>> enumerator<#= j #>;
UniTask<bool>.Awaiter awaiter<#= j #>;
bool hasCurrent<#= j #>;
bool running<#= j #>;
T<#= j #> current<#= j #>;
<# } #>
int completedCount;
bool syncRunning;
TResult result;
public _CombineLatest(<#= paramArgs(i) #>, Func<<#= typeArgs(i) #>> resultSelector, CancellationToken cancellationToken)
{
<# for(var j = 1; j <= i; j++) { #>
this.source<#= j #> = source<#= j #>;
<# } #>
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
TaskTracker.TrackActiveTask(this, 3);
}
public TResult Current => result;
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (completedCount == CompleteCount) return CompletedTasks.False;
if (enumerator1 == null)
{
<# for(var j = 1; j <= i; j++) { #>
enumerator<#= j #> = source<#= j #>.GetAsyncEnumerator(cancellationToken);
<# } #>
}
completionSource.Reset();
AGAIN:
syncRunning = true;
<# for(var j = 1; j <= i; j++) { #>
if (!running<#= j #>)
{
running<#= j #> = true;
awaiter<#= j #> = enumerator<#= j #>.MoveNextAsync().GetAwaiter();
if (awaiter<#= j #>.IsCompleted)
{
Completed<#= j #>(this);
}
else
{
awaiter<#= j #>.SourceOnCompleted(Completed<#= j #>Delegate, this);
}
}
<# } #>
if (<#= string.Join(" || ", Enumerable.Range(1, i).Select(x => $"!running{x}")) #>)
{
goto AGAIN;
}
syncRunning = false;
return new UniTask<bool>(this, completionSource.Version);
}
<# for(var j = 1; j <= i; j++) { #>
static void Completed<#= j #>(object state)
{
var self = (_CombineLatest)state;
self.running<#= j #> = false;
try
{
if (self.awaiter<#= j #>.GetResult())
{
self.hasCurrent<#= j #> = true;
self.current<#= j #> = self.enumerator<#= j #>.Current;
goto SUCCESS;
}
else
{
self.running<#= j #> = true; // as complete, no more call MoveNextAsync.
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
{
goto COMPLETE;
}
return;
}
}
catch (Exception ex)
{
self.running<#= j #> = true; // as complete, no more call MoveNextAsync.
self.completedCount = CompleteCount;
self.completionSource.TrySetException(ex);
return;
}
SUCCESS:
if (!self.TrySetResult())
{
if (self.syncRunning) return;
self.running<#= j #> = true; // as complete, no more call MoveNextAsync.
try
{
self.awaiter<#= j #> = self.enumerator<#= j #>.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
self.completedCount = CompleteCount;
self.completionSource.TrySetException(ex);
return;
}
self.awaiter<#= j #>.SourceOnCompleted(Completed<#= j #>Delegate, self);
}
return;
COMPLETE:
self.completionSource.TrySetResult(false);
return;
}
<# } #>
bool TrySetResult()
{
if (<#= string.Join(" && ", Enumerable.Range(1, i).Select(x => $"hasCurrent{x}")) #>)
{
result = resultSelector(<#= string.Join(", ", Enumerable.Range(1, i).Select(x => $"current{x}")) #>);
completionSource.TrySetResult(true);
return true;
}
else
{
return false;
}
}
public async UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
<# for(var j = 1; j <= i; j++) { #>
if (enumerator<#= j #> != null)
{
await enumerator<#= j #>.DisposeAsync();
}
<# } #>
}
}
}
<# } #>
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b1b8cfa9d17af814a971ee2224aaaaa2
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,262 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var types = new[]
{
typeof(int),
typeof(long),
typeof(float),
typeof(double),
typeof(decimal),
typeof(int?),
typeof(long?),
typeof(float?),
typeof(double?),
typeof(decimal?),
};
Func<Type, bool> IsNullable = x => x.IsGenericType;
Func<Type, string> TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name;
Func<Type, string> WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : "";
#>
using System;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
<# foreach(var (minMax, op) in new[]{("Min",">"), ("Max", "<")}) { #>
public static partial class UniTaskAsyncEnumerable
{
<# foreach(var t in types) { #>
public static UniTask<<#= TypeName(t) #>> <#= minMax #>Async(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return <#= minMax #>.<#= minMax #>Async(source, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> <#= minMax #>Async<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return <#= minMax #>.<#= minMax #>Async(source, selector, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> <#= minMax #>AwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return <#= minMax #>.<#= minMax #>AwaitAsync(source, selector, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> <#= minMax #>AwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return <#= minMax #>.<#= minMax #>AwaitWithCancellationAsync(source, selector, cancellationToken);
}
<# } #>
}
internal static partial class <#= minMax #>
{
<# foreach(var t in types) { #>
public static async UniTask<<#= TypeName(t) #>> <#= minMax #>Async(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken)
{
<#= TypeName(t) #> value = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = e.Current;
<# if (IsNullable(t)) { #>
if(value == null) continue;
<# } #>
goto NEXT_LOOP;
}
<# if (IsNullable(t)) { #>
return default;
<# } else { #>
throw Error.NoElements();
<# } #>
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = e.Current;
<# if (IsNullable(t)) { #>
if( x == null) continue;
<# } #>
if (value <#= op #> x)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<<#= TypeName(t) #>> <#= minMax #>Async<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> value = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = selector(e.Current);
<# if (IsNullable(t)) { #>
if(value == null) continue;
<# } #>
goto NEXT_LOOP;
}
<# if (IsNullable(t)) { #>
return default;
<# } else { #>
throw Error.NoElements();
<# } #>
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = selector(e.Current);
<# if (IsNullable(t)) { #>
if( x == null) continue;
<# } #>
if (value <#= op #> x)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<<#= TypeName(t) #>> <#= minMax #>AwaitAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> value = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = await selector(e.Current);
<# if (IsNullable(t)) { #>
if(value == null) continue;
<# } #>
goto NEXT_LOOP;
}
<# if (IsNullable(t)) { #>
return default;
<# } else { #>
throw Error.NoElements();
<# } #>
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = await selector(e.Current);
<# if (IsNullable(t)) { #>
if( x == null) continue;
<# } #>
if (value <#= op #> x)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<<#= TypeName(t) #>> <#= minMax #>AwaitWithCancellationAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> value = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = await selector(e.Current, cancellationToken);
<# if (IsNullable(t)) { #>
if(value == null) continue;
<# } #>
goto NEXT_LOOP;
}
<# if (IsNullable(t)) { #>
return default;
<# } else { #>
throw Error.NoElements();
<# } #>
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = await selector(e.Current, cancellationToken);
<# if (IsNullable(t)) { #>
if( x == null) continue;
<# } #>
if (value <#= op #> x)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
<# } #>
}
<# } #>
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 18108e9feb2ec40498df573cfef2ea15
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,167 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var types = new[]
{
typeof(int),
typeof(long),
typeof(float),
typeof(double),
typeof(decimal),
typeof(int?),
typeof(long?),
typeof(float?),
typeof(double?),
typeof(decimal?),
};
Func<Type, bool> IsNullable = x => x.IsGenericType;
Func<Type, string> TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name;
Func<Type, string> WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : "";
#>
using System;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
<# foreach(var t in types) { #>
public static UniTask<<#= TypeName(t) #>> SumAsync(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Sum.SumAsync(source, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> SumAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Sum.SumAsync(source, selector, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> SumAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Sum.SumAwaitAsync(source, selector, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> SumAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Sum.SumAwaitWithCancellationAsync(source, selector, cancellationToken);
}
<# } #>
}
internal static class Sum
{
<# foreach(var t in types) { #>
public static async UniTask<<#= TypeName(t) #>> SumAsync(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken)
{
<#= TypeName(t) #> sum = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
sum += e.Current<#= WithSuffix(t) #>;
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return sum;
}
public static async UniTask<<#= TypeName(t) #>> SumAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> sum = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
sum += selector(e.Current)<#= WithSuffix(t) #>;
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return sum;
}
public static async UniTask<<#= TypeName(t) #>> SumAwaitAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> sum = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
sum += (await selector(e.Current))<#= WithSuffix(t) #>;
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return sum;
}
public static async UniTask<<#= TypeName(t) #>> SumAwaitWithCancellationAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> sum = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
sum += (await selector(e.Current, cancellationToken))<#= WithSuffix(t) #>;
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return sum;
}
<# } #>
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b61271ca8e712494ab1ce2d10b180b6f
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 3c463ff8cd00c4e449ca9bfe6a6c6b4d
guid: 669f5459819f7284ca1b35f4d55fe226
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -4,38 +4,50 @@ namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
{
return new EveryUpdate(updateTiming);
return new EveryUpdate(updateTiming, cancelImmediately);
}
}
internal class EveryUpdate : IUniTaskAsyncEnumerable<AsyncUnit>
{
readonly PlayerLoopTiming updateTiming;
readonly bool cancelImmediately;
public EveryUpdate(PlayerLoopTiming updateTiming)
public EveryUpdate(PlayerLoopTiming updateTiming, bool cancelImmediately)
{
this.updateTiming = updateTiming;
this.cancelImmediately = cancelImmediately;
}
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new _EveryUpdate(updateTiming, cancellationToken);
return new _EveryUpdate(updateTiming, cancellationToken, cancelImmediately);
}
class _EveryUpdate : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
{
readonly PlayerLoopTiming updateTiming;
CancellationToken cancellationToken;
readonly CancellationToken cancellationToken;
readonly CancellationTokenRegistration cancellationTokenRegistration;
bool disposed;
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken, bool cancelImmediately)
{
this.updateTiming = updateTiming;
this.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (_EveryUpdate)state;
source.completionSource.TrySetCanceled(source.cancellationToken);
}, this);
}
TaskTracker.TrackActiveTask(this, 2);
PlayerLoopHelper.AddAction(updateTiming, this);
}
@@ -44,10 +56,14 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
if (disposed) return CompletedTasks.False;
completionSource.Reset();
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
}
return new UniTask<bool>(this, completionSource.Version);
}
@@ -55,6 +71,7 @@ namespace Cysharp.Threading.Tasks.Linq
{
if (!disposed)
{
cancellationTokenRegistration.Dispose();
disposed = true;
TaskTracker.RemoveTracking(this);
}
@@ -63,7 +80,13 @@ namespace Cysharp.Threading.Tasks.Linq
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested)
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
return false;
}
if (disposed)
{
completionSource.TrySetResult(false);
return false;

View File

@@ -7,7 +7,7 @@ namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TProperty> EveryValueChanged<TTarget, TProperty>(TTarget target, Func<TTarget, TProperty> propertySelector, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<TProperty> equalityComparer = null)
public static IUniTaskAsyncEnumerable<TProperty> EveryValueChanged<TTarget, TProperty>(TTarget target, Func<TTarget, TProperty> propertySelector, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<TProperty> equalityComparer = null, bool cancelImmediately = false)
where TTarget : class
{
var unityObject = target as UnityEngine.Object;
@@ -15,11 +15,11 @@ namespace Cysharp.Threading.Tasks.Linq
if (isUnityObject)
{
return new EveryValueChangedUnityObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming);
return new EveryValueChangedUnityObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming, cancelImmediately);
}
else
{
return new EveryValueChangedStandardObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming);
return new EveryValueChangedStandardObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming, cancelImmediately);
}
}
}
@@ -30,18 +30,20 @@ namespace Cysharp.Threading.Tasks.Linq
readonly Func<TTarget, TProperty> propertySelector;
readonly IEqualityComparer<TProperty> equalityComparer;
readonly PlayerLoopTiming monitorTiming;
readonly bool cancelImmediately;
public EveryValueChangedUnityObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming)
public EveryValueChangedUnityObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, bool cancelImmediately)
{
this.target = target;
this.propertySelector = propertySelector;
this.equalityComparer = equalityComparer;
this.monitorTiming = monitorTiming;
this.cancelImmediately = cancelImmediately;
}
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken);
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken, cancelImmediately);
}
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
@@ -50,13 +52,14 @@ namespace Cysharp.Threading.Tasks.Linq
readonly UnityEngine.Object targetAsUnityObject;
readonly IEqualityComparer<TProperty> equalityComparer;
readonly Func<TTarget, TProperty> propertySelector;
CancellationToken cancellationToken;
readonly CancellationToken cancellationToken;
readonly CancellationTokenRegistration cancellationTokenRegistration;
bool first;
TProperty currentValue;
bool disposed;
public _EveryValueChanged(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken)
public _EveryValueChanged(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken, bool cancelImmediately)
{
this.target = target;
this.targetAsUnityObject = target as UnityEngine.Object;
@@ -64,6 +67,16 @@ namespace Cysharp.Threading.Tasks.Linq
this.equalityComparer = equalityComparer;
this.cancellationToken = cancellationToken;
this.first = true;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (_EveryValueChanged)state;
source.completionSource.TrySetCanceled(source.cancellationToken);
}, this);
}
TaskTracker.TrackActiveTask(this, 2);
PlayerLoopHelper.AddAction(monitorTiming, this);
}
@@ -72,8 +85,15 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
if (disposed) return CompletedTasks.False;
completionSource.Reset();
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
return new UniTask<bool>(this, completionSource.Version);
}
if (first)
{
@@ -86,7 +106,6 @@ namespace Cysharp.Threading.Tasks.Linq
return CompletedTasks.True;
}
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
@@ -94,6 +113,7 @@ namespace Cysharp.Threading.Tasks.Linq
{
if (!disposed)
{
cancellationTokenRegistration.Dispose();
disposed = true;
TaskTracker.RemoveTracking(this);
}
@@ -102,13 +122,18 @@ namespace Cysharp.Threading.Tasks.Linq
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested || targetAsUnityObject == null) // destroyed = cancel.
if (disposed || targetAsUnityObject == null)
{
completionSource.TrySetResult(false);
DisposeAsync().Forget();
return false;
}
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
return false;
}
TProperty nextValue = default(TProperty);
try
{
@@ -139,18 +164,20 @@ namespace Cysharp.Threading.Tasks.Linq
readonly Func<TTarget, TProperty> propertySelector;
readonly IEqualityComparer<TProperty> equalityComparer;
readonly PlayerLoopTiming monitorTiming;
readonly bool cancelImmediately;
public EveryValueChangedStandardObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming)
public EveryValueChangedStandardObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, bool cancelImmediately)
{
this.target = new WeakReference<TTarget>(target, false);
this.propertySelector = propertySelector;
this.equalityComparer = equalityComparer;
this.monitorTiming = monitorTiming;
this.cancelImmediately = cancelImmediately;
}
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken);
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken, cancelImmediately);
}
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
@@ -158,19 +185,30 @@ namespace Cysharp.Threading.Tasks.Linq
readonly WeakReference<TTarget> target;
readonly IEqualityComparer<TProperty> equalityComparer;
readonly Func<TTarget, TProperty> propertySelector;
CancellationToken cancellationToken;
readonly CancellationToken cancellationToken;
readonly CancellationTokenRegistration cancellationTokenRegistration;
bool first;
TProperty currentValue;
bool disposed;
public _EveryValueChanged(WeakReference<TTarget> target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken)
public _EveryValueChanged(WeakReference<TTarget> target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken, bool cancelImmediately)
{
this.target = target;
this.propertySelector = propertySelector;
this.equalityComparer = equalityComparer;
this.cancellationToken = cancellationToken;
this.first = true;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (_EveryValueChanged)state;
source.completionSource.TrySetCanceled(source.cancellationToken);
}, this);
}
TaskTracker.TrackActiveTask(this, 2);
PlayerLoopHelper.AddAction(monitorTiming, this);
}
@@ -179,8 +217,16 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask<bool> MoveNextAsync()
{
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
if (disposed) return CompletedTasks.False;
completionSource.Reset();
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
return new UniTask<bool>(this, completionSource.Version);
}
if (first)
{
first = false;
@@ -192,7 +238,6 @@ namespace Cysharp.Threading.Tasks.Linq
return CompletedTasks.True;
}
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
@@ -200,6 +245,7 @@ namespace Cysharp.Threading.Tasks.Linq
{
if (!disposed)
{
cancellationTokenRegistration.Dispose();
disposed = true;
TaskTracker.RemoveTracking(this);
}
@@ -208,13 +254,19 @@ namespace Cysharp.Threading.Tasks.Linq
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested || !target.TryGetTarget(out var t))
if (disposed || !target.TryGetTarget(out var t))
{
completionSource.TrySetResult(false);
DisposeAsync().Forget();
return false;
}
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
return false;
}
TProperty nextValue = default(TProperty);
try
{

View File

@@ -6,32 +6,32 @@ namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
{
return new Timer(dueTime, null, updateTiming, ignoreTimeScale);
return new Timer(dueTime, null, updateTiming, ignoreTimeScale, cancelImmediately);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
{
return new Timer(dueTime, period, updateTiming, ignoreTimeScale);
return new Timer(dueTime, period, updateTiming, ignoreTimeScale, cancelImmediately);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
{
return new Timer(period, period, updateTiming, ignoreTimeScale);
return new Timer(period, period, updateTiming, ignoreTimeScale, cancelImmediately);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
{
if (dueTimeFrameCount < 0)
{
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
}
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
return new TimerFrame(dueTimeFrameCount, null, updateTiming, cancelImmediately);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
{
if (dueTimeFrameCount < 0)
{
@@ -42,16 +42,16 @@ namespace Cysharp.Threading.Tasks.Linq
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
}
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancelImmediately);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
{
if (intervalFrameCount < 0)
{
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
}
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming, cancelImmediately);
}
}
@@ -61,18 +61,20 @@ namespace Cysharp.Threading.Tasks.Linq
readonly TimeSpan dueTime;
readonly TimeSpan? period;
readonly bool ignoreTimeScale;
readonly bool cancelImmediately;
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale)
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, bool cancelImmediately)
{
this.updateTiming = updateTiming;
this.dueTime = dueTime;
this.period = period;
this.ignoreTimeScale = ignoreTimeScale;
this.cancelImmediately = cancelImmediately;
}
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new _Timer(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken);
return new _Timer(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken, cancelImmediately);
}
class _Timer : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
@@ -81,7 +83,8 @@ namespace Cysharp.Threading.Tasks.Linq
readonly float? period;
readonly PlayerLoopTiming updateTiming;
readonly bool ignoreTimeScale;
CancellationToken cancellationToken;
readonly CancellationToken cancellationToken;
readonly CancellationTokenRegistration cancellationTokenRegistration;
int initialFrame;
float elapsed;
@@ -89,7 +92,7 @@ namespace Cysharp.Threading.Tasks.Linq
bool completed;
bool disposed;
public _Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken)
public _Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken, bool cancelImmediately)
{
this.dueTime = (float)dueTime.TotalSeconds;
this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
@@ -105,6 +108,16 @@ namespace Cysharp.Threading.Tasks.Linq
this.updateTiming = updateTiming;
this.ignoreTimeScale = ignoreTimeScale;
this.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (_Timer)state;
source.completionSource.TrySetCanceled(source.cancellationToken);
}, this);
}
TaskTracker.TrackActiveTask(this, 2);
PlayerLoopHelper.AddAction(updateTiming, this);
}
@@ -114,12 +127,16 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested || completed) return CompletedTasks.False;
if (disposed || completed) return CompletedTasks.False;
// reset value here.
this.elapsed = 0;
completionSource.Reset();
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
}
return new UniTask<bool>(this, completionSource.Version);
}
@@ -127,6 +144,7 @@ namespace Cysharp.Threading.Tasks.Linq
{
if (!disposed)
{
cancellationTokenRegistration.Dispose();
disposed = true;
TaskTracker.RemoveTracking(this);
}
@@ -135,11 +153,16 @@ namespace Cysharp.Threading.Tasks.Linq
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested)
if (disposed)
{
completionSource.TrySetResult(false);
return false;
}
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
return false;
}
if (dueTimePhase)
{
@@ -187,24 +210,27 @@ namespace Cysharp.Threading.Tasks.Linq
readonly PlayerLoopTiming updateTiming;
readonly int dueTimeFrameCount;
readonly int? periodFrameCount;
readonly bool cancelImmediately;
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming)
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, bool cancelImmediately)
{
this.updateTiming = updateTiming;
this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount;
this.cancelImmediately = cancelImmediately;
}
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken);
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken, cancelImmediately);
}
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
{
readonly int dueTimeFrameCount;
readonly int? periodFrameCount;
CancellationToken cancellationToken;
readonly CancellationToken cancellationToken;
readonly CancellationTokenRegistration cancellationTokenRegistration;
int initialFrame;
int currentFrame;
@@ -212,7 +238,7 @@ namespace Cysharp.Threading.Tasks.Linq
bool completed;
bool disposed;
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken, bool cancelImmediately)
{
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
if (periodFrameCount != null)
@@ -225,6 +251,15 @@ namespace Cysharp.Threading.Tasks.Linq
this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount;
this.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (_TimerFrame)state;
source.completionSource.TrySetCanceled(source.cancellationToken);
}, this);
}
TaskTracker.TrackActiveTask(this, 2);
PlayerLoopHelper.AddAction(updateTiming, this);
@@ -234,13 +269,15 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested || completed) return CompletedTasks.False;
if (disposed || completed) return CompletedTasks.False;
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
}
// reset value here.
this.currentFrame = 0;
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
@@ -249,6 +286,7 @@ namespace Cysharp.Threading.Tasks.Linq
{
if (!disposed)
{
cancellationTokenRegistration.Dispose();
disposed = true;
TaskTracker.RemoveTracking(this);
}
@@ -257,7 +295,12 @@ namespace Cysharp.Threading.Tasks.Linq
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested)
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
return false;
}
if (disposed)
{
completionSource.TrySetResult(false);
return false;

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1b92f798107ca0d40b1053ca41307c56
guid: 85c0c768ced512e42b24021b3258b669
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,208 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var empty = new (string, string)[0];
var triggers = new (string triggerName, string methodName, string returnType, string handlerInterface, (string argType, string argName)[] arguments)[]
{
("AnimatorIK", "OnAnimatorIK", "int", null, new []{ ("int", "layerIndex") }),
("AnimatorMove", "OnAnimatorMove", "AsyncUnit", null, empty),
("OnCanvasGroupChanged", "OnCanvasGroupChanged", "AsyncUnit", null, empty ),
("CollisionEnter2D", "OnCollisionEnter2D", "Collision2D", null, new []{ ("Collision2D", "coll") }),
("CollisionExit2D", "OnCollisionExit2D", "Collision2D", null, new []{ ("Collision2D", "coll") }),
("CollisionStay2D", "OnCollisionStay2D", "Collision2D", null, new []{ ("Collision2D", "coll") }),
("CollisionEnter", "OnCollisionEnter", "Collision", null, new []{ ("Collision", "coll") }),
("CollisionExit", "OnCollisionExit", "Collision", null, new []{ ("Collision", "coll") }),
("CollisionStay", "OnCollisionStay", "Collision", null, new []{ ("Collision", "coll") }),
("Enable", "OnEnable", "AsyncUnit", null, empty),
("Disable", "OnDisable", "AsyncUnit", null, empty),
("JointBreak", "OnJointBreak", "float", null, new []{ ("float", "breakForce") }),
("JointBreak2D", "OnJointBreak2D", "Joint2D", null, new []{ ("Joint2D", "brokenJoint") }),
("Update", "Update", "AsyncUnit", null, empty),
("FixedUpdate", "FixedUpdate", "AsyncUnit", null, empty),
("LateUpdate", "LateUpdate", "AsyncUnit", null, empty),
("ParticleCollision", "OnParticleCollision", "GameObject", null, new []{ ("GameObject", "other") }),
("RectTransformDimensionsChange", "OnRectTransformDimensionsChange", "AsyncUnit", null, empty),
("RectTransformRemoved", "OnRectTransformRemoved", "AsyncUnit", null, empty),
("BeforeTransformParentChanged", "OnBeforeTransformParentChanged", "AsyncUnit", null, empty),
("TransformParentChanged", "OnTransformParentChanged", "AsyncUnit", null, empty),
("TransformChildrenChanged", "OnTransformChildrenChanged", "AsyncUnit", null, empty),
("TriggerEnter2D", "OnTriggerEnter2D", "Collider2D", null, new []{ ("Collider2D", "other") }),
("TriggerExit2D", "OnTriggerExit2D", "Collider2D", null, new []{ ("Collider2D", "other") }),
("TriggerStay2D", "OnTriggerStay2D", "Collider2D", null, new []{ ("Collider2D", "other") }),
("TriggerEnter", "OnTriggerEnter", "Collider", null, new []{ ("Collider", "other") }),
("TriggerExit", "OnTriggerExit", "Collider", null, new []{ ("Collider", "other") }),
("TriggerStay", "OnTriggerStay", "Collider", null, new []{ ("Collider", "other") }),
("BecameInvisible", "OnBecameInvisible", "AsyncUnit", null, empty),
("BecameVisible", "OnBecameVisible", "AsyncUnit", null, empty),
// Mouse... #if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
("MouseDown", "OnMouseDown", "AsyncUnit", null, empty),
("MouseDrag", "OnMouseDrag", "AsyncUnit", null, empty),
("MouseEnter", "OnMouseEnter", "AsyncUnit", null, empty),
("MouseExit", "OnMouseExit", "AsyncUnit", null, empty),
("MouseOver", "OnMouseOver", "AsyncUnit", null, empty),
("MouseUp", "OnMouseUp", "AsyncUnit", null, empty),
("MouseUpAsButton", "OnMouseUpAsButton", "AsyncUnit", null, empty),
// new in v2
("ApplicationFocus", "OnApplicationFocus", "bool", null, new []{("bool", "hasFocus") }),
("ApplicationPause", "OnApplicationPause", "bool", null, new []{("bool", "pauseStatus") }),
("ApplicationQuit", "OnApplicationQuit", "AsyncUnit", null, empty),
("AudioFilterRead", "OnAudioFilterRead", "(float[] data, int channels)", null, new[]{("float[]", "data"), ("int", "channels")}),
("ControllerColliderHit", "OnControllerColliderHit", "ControllerColliderHit", null, new[]{("ControllerColliderHit", "hit")}),
("DrawGizmos", "OnDrawGizmos", "AsyncUnit", null, empty),
("DrawGizmosSelected", "OnDrawGizmosSelected", "AsyncUnit", null, empty),
("GUI", "OnGUI", "AsyncUnit", null, empty),
("ParticleSystemStopped", "OnParticleSystemStopped", "AsyncUnit", null, empty),
("ParticleTrigger", "OnParticleTrigger", "AsyncUnit", null, empty),
("PostRender", "OnPostRender", "AsyncUnit", null, empty),
("PreCull", "OnPreCull", "AsyncUnit", null, empty),
("PreRender", "OnPreRender", "AsyncUnit", null, empty),
("RenderImage", "OnRenderImage", "(RenderTexture source, RenderTexture destination)", null, new[]{("RenderTexture", "source"), ("RenderTexture", "destination")}),
("RenderObject", "OnRenderObject", "AsyncUnit", null, empty),
("ServerInitialized", "OnServerInitialized", "AsyncUnit", null, empty),
("Validate", "OnValidate", "AsyncUnit", null, empty),
("WillRenderObject", "OnWillRenderObject", "AsyncUnit", null, empty),
("Reset", "Reset", "AsyncUnit", null, empty),
// uGUI
("BeginDrag", "OnBeginDrag", "PointerEventData", "IBeginDragHandler", new []{ ("PointerEventData", "eventData") }),
("Cancel", "OnCancel", "BaseEventData", "ICancelHandler", new []{ ("BaseEventData", "eventData") }),
("Deselect", "OnDeselect", "BaseEventData", "IDeselectHandler", new []{ ("BaseEventData", "eventData") }),
("Drag", "OnDrag", "PointerEventData", "IDragHandler", new []{ ("PointerEventData", "eventData") }),
("Drop", "OnDrop", "PointerEventData", "IDropHandler", new []{ ("PointerEventData", "eventData") }),
("EndDrag", "OnEndDrag", "PointerEventData", "IEndDragHandler", new []{ ("PointerEventData", "eventData") }),
("InitializePotentialDrag", "OnInitializePotentialDrag", "PointerEventData", "IInitializePotentialDragHandler", new []{ ("PointerEventData", "eventData") }),
("Move", "OnMove", "AxisEventData", "IMoveHandler", new []{ ("AxisEventData", "eventData") }),
("PointerClick", "OnPointerClick", "PointerEventData", "IPointerClickHandler", new []{ ("PointerEventData", "eventData") }),
("PointerDown", "OnPointerDown", "PointerEventData", "IPointerDownHandler", new []{ ("PointerEventData", "eventData") }),
("PointerEnter", "OnPointerEnter", "PointerEventData", "IPointerEnterHandler", new []{ ("PointerEventData", "eventData") }),
("PointerExit", "OnPointerExit", "PointerEventData", "IPointerExitHandler", new []{ ("PointerEventData", "eventData") }),
("PointerUp", "OnPointerUp", "PointerEventData", "IPointerUpHandler", new []{ ("PointerEventData", "eventData") }),
("Scroll", "OnScroll", "PointerEventData", "IScrollHandler", new []{ ("PointerEventData", "eventData") }),
("Select", "OnSelect", "BaseEventData", "ISelectHandler", new []{ ("BaseEventData", "eventData") }),
("Submit", "OnSubmit", "BaseEventData", "ISubmitHandler", new []{ ("BaseEventData", "eventData") }),
("UpdateSelected", "OnUpdateSelected", "BaseEventData", "IUpdateSelectedHandler", new []{ ("BaseEventData", "eventData") }),
// 2019.3
("ParticleUpdateJobScheduled", "OnParticleUpdateJobScheduled", "UnityEngine.ParticleSystemJobs.ParticleSystemJobData", null, new[]{("UnityEngine.ParticleSystemJobs.ParticleSystemJobData", "particles")}),
// Oneshot
// Awake, Start, Destroy
};
triggers = triggers.OrderBy(x => x.handlerInterface != null).ThenBy(x => x.handlerInterface != null ? x.handlerInterface : x.methodName).ToArray();
Func<string, string> ToInterfaceName = x => $"IAsync{x}Handler";
Func<string, string> ToUniTaskName = x => x == "AsyncUnit" ? "UniTask" : $"UniTask<{x}>";
Func<string, string> ToCastUniTasSourceType = x => x == "AsyncUnit" ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
Func<string, string> OnInvokeSuffix = x => x == "AsyncUnit" ? ".AsUniTask()" : $"";
Func<(string argType, string argName)[], string> BuildMethodArgument = x => string.Join(", ", x.Select(y => y.argType + " " + y.argName));
Func<(string argType, string argName)[], string> BuildResultParameter = x => x.Length == 0 ? "AsyncUnit.Default" : "(" + string.Join(", ", x.Select(y => y.argName)) + ")";
Func<string, bool> IsParticleSystem = x => x == "ParticleUpdateJobScheduled";
Func<string, bool> IsMouseTrigger = x => x.StartsWith("Mouse");
Func<string, string> RequirePhysicsModule = x => (x.StartsWith("Collision") || x.StartsWith("Collider") || x.StartsWith("ControllerCollider") || x.StartsWith("Joint") || x.StartsWith("Trigger"))
? (x.Contains("2D") ? "UNITASK_PHYSICS2D_SUPPORT" : "UNITASK_PHYSICS_SUPPORT")
: null;
Func<string, bool> IsUguiSystem = x => x != null;
#>
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Threading;
using UnityEngine;
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
using UnityEngine.EventSystems;
#endif
namespace Cysharp.Threading.Tasks.Triggers
{
<# foreach(var t in triggers) { #>
#region <#= t.triggerName #>
<# if(IsUguiSystem(t.handlerInterface)) { #>
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
<# } #>
<# if(IsParticleSystem(t.triggerName)) { #>
#if UNITY_2019_3_OR_NEWER && (!UNITY_2019_1_OR_NEWER || UNITASK_PARTICLESYSTEM_SUPPORT)
<# } #>
<# if(IsMouseTrigger(t.triggerName)) { #>
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
<# } #>
<# if(RequirePhysicsModule(t.triggerName) != null) { #>
#if !UNITY_2019_1_OR_NEWER || <#= RequirePhysicsModule(t.triggerName) #>
<# } #>
public interface <#= ToInterfaceName(t.methodName) #>
{
<#= ToUniTaskName(t.returnType) #> <#= t.methodName #>Async();
}
public partial class AsyncTriggerHandler<T> : <#= ToInterfaceName(t.methodName) #>
{
<#= ToUniTaskName(t.returnType) #> <#= ToInterfaceName(t.methodName) #>.<#= t.methodName #>Async()
{
core.Reset();
return new <#= ToUniTaskName(t.returnType) #>((<#= ToCastUniTasSourceType(t.returnType) #>)(object)this, core.Version);
}
}
public static partial class AsyncTriggerExtensions
{
public static Async<#= t.triggerName #>Trigger GetAsync<#= t.triggerName #>Trigger(this GameObject gameObject)
{
return GetOrAddComponent<Async<#= t.triggerName #>Trigger>(gameObject);
}
public static Async<#= t.triggerName #>Trigger GetAsync<#= t.triggerName #>Trigger(this Component component)
{
return component.gameObject.GetAsync<#= t.triggerName #>Trigger();
}
}
[DisallowMultipleComponent]
public sealed class Async<#= t.triggerName #>Trigger : AsyncTriggerBase<<#= t.returnType #>><#= (t.handlerInterface == null) ? "" : $", {t.handlerInterface}" #>
{
void <#= (t.handlerInterface == null) ? "" : $"{t.handlerInterface}." #><#= t.methodName #>(<#= BuildMethodArgument(t.arguments) #>)
{
RaiseEvent(<#= BuildResultParameter(t.arguments) #>);
}
public <#= ToInterfaceName(t.methodName) #> Get<#= t.methodName #>AsyncHandler()
{
return new AsyncTriggerHandler<<#= t.returnType #>>(this, false);
}
public <#= ToInterfaceName(t.methodName) #> Get<#= t.methodName #>AsyncHandler(CancellationToken cancellationToken)
{
return new AsyncTriggerHandler<<#= t.returnType #>>(this, cancellationToken, false);
}
public <#= ToUniTaskName(t.returnType) #> <#= t.methodName #>Async()
{
return ((<#= ToInterfaceName(t.methodName) #>)new AsyncTriggerHandler<<#= t.returnType #>>(this, true)).<#= t.methodName #>Async();
}
public <#= ToUniTaskName(t.returnType) #> <#= t.methodName #>Async(CancellationToken cancellationToken)
{
return ((<#= ToInterfaceName(t.methodName) #>)new AsyncTriggerHandler<<#= t.returnType #>>(this, cancellationToken, true)).<#= t.methodName #>Async();
}
}
<# if(IsUguiSystem(t.handlerInterface)) { #>
#endif
<# } #>
<# if(RequirePhysicsModule(t.triggerName) != null) { #>
#endif
<# } #>
<# if(IsParticleSystem(t.triggerName) || IsMouseTrigger(t.triggerName)) { #>
#endif
<# } #>
#endregion
<# } #>
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3ca26d0cd9373354c8cd147490f32c8e
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -33,14 +33,14 @@ namespace Cysharp.Threading.Tasks
return new YieldAwaitable(timing);
}
public static UniTask Yield(CancellationToken cancellationToken)
public static UniTask Yield(CancellationToken cancellationToken, bool cancelImmediately = false)
{
return new UniTask(YieldPromise.Create(PlayerLoopTiming.Update, cancellationToken, out var token), token);
return new UniTask(YieldPromise.Create(PlayerLoopTiming.Update, cancellationToken, cancelImmediately, out var token), token);
}
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken)
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately = false)
{
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
return new UniTask(YieldPromise.Create(timing, cancellationToken, cancelImmediately, out var token), token);
}
/// <summary>
@@ -48,7 +48,7 @@ namespace Cysharp.Threading.Tasks
/// </summary>
public static UniTask NextFrame()
{
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, CancellationToken.None, out var token), token);
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, CancellationToken.None, false, out var token), token);
}
/// <summary>
@@ -56,23 +56,23 @@ namespace Cysharp.Threading.Tasks
/// </summary>
public static UniTask NextFrame(PlayerLoopTiming timing)
{
return new UniTask(NextFramePromise.Create(timing, CancellationToken.None, out var token), token);
return new UniTask(NextFramePromise.Create(timing, CancellationToken.None, false, out var token), token);
}
/// <summary>
/// Similar as UniTask.Yield but guaranteed run on next frame.
/// </summary>
public static UniTask NextFrame(CancellationToken cancellationToken)
public static UniTask NextFrame(CancellationToken cancellationToken, bool cancelImmediately = false)
{
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, cancellationToken, out var token), token);
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, cancellationToken, cancelImmediately, out var token), token);
}
/// <summary>
/// Similar as UniTask.Yield but guaranteed run on next frame.
/// </summary>
public static UniTask NextFrame(PlayerLoopTiming timing, CancellationToken cancellationToken)
public static UniTask NextFrame(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately = false)
{
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
return new UniTask(NextFramePromise.Create(timing, cancellationToken, cancelImmediately, out var token), token);
}
#if UNITY_2023_1_OR_NEWER
@@ -88,15 +88,21 @@ namespace Cysharp.Threading.Tasks
}
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken)
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken, bool cancelImmediately = false)
{
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken, cancelImmediately);
}
#endif
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner, CancellationToken cancellationToken = default)
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner)
{
var source = WaitForEndOfFramePromise.Create(coroutineRunner, cancellationToken, out var token);
var source = WaitForEndOfFramePromise.Create(coroutineRunner, CancellationToken.None, false, out var token);
return new UniTask(source, token);
}
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, bool cancelImmediately = false)
{
var source = WaitForEndOfFramePromise.Create(coroutineRunner, cancellationToken, cancelImmediately, out var token);
return new UniTask(source, token);
}
@@ -113,50 +119,50 @@ namespace Cysharp.Threading.Tasks
/// <summary>
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken).
/// </summary>
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken)
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken, bool cancelImmediately = false)
{
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken);
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken, cancelImmediately);
}
public static UniTask WaitForSeconds(float duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask WaitForSeconds(float duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
return Delay(Mathf.RoundToInt(1000 * duration), ignoreTimeScale, delayTiming, cancellationToken);
return Delay(Mathf.RoundToInt(1000 * duration), ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
}
public static UniTask WaitForSeconds(int duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask WaitForSeconds(int duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
return Delay(1000 * duration, ignoreTimeScale, delayTiming, cancellationToken);
return Delay(1000 * duration, ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
}
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
if (delayFrameCount < 0)
{
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. delayFrameCount:" + delayFrameCount);
}
return new UniTask(DelayFramePromise.Create(delayFrameCount, delayTiming, cancellationToken, out var token), token);
return new UniTask(DelayFramePromise.Create(delayFrameCount, delayTiming, cancellationToken, cancelImmediately, out var token), token);
}
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken);
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
}
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
var delayType = ignoreTimeScale ? DelayType.UnscaledDeltaTime : DelayType.DeltaTime;
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken, cancelImmediately);
}
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken, cancelImmediately);
}
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
if (delayTimeSpan < TimeSpan.Zero)
{
@@ -175,16 +181,16 @@ namespace Cysharp.Threading.Tasks
{
case DelayType.UnscaledDeltaTime:
{
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
}
case DelayType.Realtime:
{
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
}
case DelayType.DeltaTime:
default:
{
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
}
}
}
@@ -201,13 +207,14 @@ namespace Cysharp.Threading.Tasks
}
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<object> core;
YieldPromise()
{
}
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -219,8 +226,16 @@ namespace Cysharp.Threading.Tasks
result = new YieldPromise();
}
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (YieldPromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -274,6 +289,7 @@ namespace Cysharp.Threading.Tasks
TaskTracker.RemoveTracking(this);
core.Reset();
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -290,14 +306,15 @@ namespace Cysharp.Threading.Tasks
}
int frameCount;
CancellationToken cancellationToken;
UniTaskCompletionSourceCore<AsyncUnit> core;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
NextFramePromise()
{
}
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -312,6 +329,15 @@ namespace Cysharp.Threading.Tasks
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (NextFramePromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
@@ -369,6 +395,7 @@ namespace Cysharp.Threading.Tasks
TaskTracker.RemoveTracking(this);
core.Reset();
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -384,14 +411,15 @@ namespace Cysharp.Threading.Tasks
TaskPool.RegisterSizeGetter(typeof(WaitForEndOfFramePromise), () => pool.Size);
}
CancellationToken cancellationToken;
UniTaskCompletionSourceCore<object> core;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
WaitForEndOfFramePromise()
{
}
public static IUniTaskSource Create(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -405,6 +433,15 @@ namespace Cysharp.Threading.Tasks
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (WaitForEndOfFramePromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
coroutineRunner.StartCoroutine(result);
@@ -446,6 +483,7 @@ namespace Cysharp.Threading.Tasks
core.Reset();
Reset(); // Reset Enumerator
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
@@ -494,6 +532,7 @@ namespace Cysharp.Threading.Tasks
int initialFrame;
int delayFrameCount;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
int currentFrameCount;
UniTaskCompletionSourceCore<AsyncUnit> core;
@@ -502,7 +541,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -518,6 +557,15 @@ namespace Cysharp.Threading.Tasks
result.cancellationToken = cancellationToken;
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (DelayFramePromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
@@ -604,6 +652,7 @@ namespace Cysharp.Threading.Tasks
currentFrameCount = default;
delayFrameCount = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -623,6 +672,7 @@ namespace Cysharp.Threading.Tasks
float delayTimeSpan;
float elapsed;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<object> core;
@@ -630,7 +680,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -647,6 +697,15 @@ namespace Cysharp.Threading.Tasks
result.cancellationToken = cancellationToken;
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (DelayPromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
@@ -715,6 +774,7 @@ namespace Cysharp.Threading.Tasks
delayTimeSpan = default;
elapsed = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -734,6 +794,7 @@ namespace Cysharp.Threading.Tasks
float elapsed;
int initialFrame;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<object> core;
@@ -741,7 +802,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -758,6 +819,15 @@ namespace Cysharp.Threading.Tasks
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (DelayIgnoreTimeScalePromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
@@ -826,6 +896,7 @@ namespace Cysharp.Threading.Tasks
delayFrameTimeSpan = default;
elapsed = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -844,6 +915,7 @@ namespace Cysharp.Threading.Tasks
long delayTimeSpanTicks;
ValueStopwatch stopwatch;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<AsyncUnit> core;
@@ -851,7 +923,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -867,6 +939,15 @@ namespace Cysharp.Threading.Tasks
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (DelayRealtimePromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
@@ -931,6 +1012,7 @@ namespace Cysharp.Threading.Tasks
core.Reset();
stopwatch = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}

View File

@@ -9,30 +9,30 @@ namespace Cysharp.Threading.Tasks
{
public partial struct UniTask
{
public static UniTask WaitUntil(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask WaitUntil(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
return new UniTask(WaitUntilPromise.Create(predicate, timing, cancellationToken, out var token), token);
return new UniTask(WaitUntilPromise.Create(predicate, timing, cancellationToken, cancelImmediately, out var token), token);
}
public static UniTask WaitWhile(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask WaitWhile(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, out var token), token);
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, cancelImmediately, out var token), token);
}
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update)
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update, bool completeImmediately = false)
{
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, out var token), token);
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, completeImmediately, out var token), token);
}
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
where T : class
{
var unityObject = target as UnityEngine.Object;
var isUnityObject = target is UnityEngine.Object; // don't use (unityObject == null)
return new UniTask<U>(isUnityObject
? WaitUntilValueChangedUnityObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out var token)
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out token), token);
? WaitUntilValueChangedUnityObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, cancelImmediately, out var token)
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, cancelImmediately, out token), token);
}
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
@@ -48,6 +48,7 @@ namespace Cysharp.Threading.Tasks
Func<bool> predicate;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<object> core;
@@ -55,7 +56,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -70,6 +71,15 @@ namespace Cysharp.Threading.Tasks
result.predicate = predicate;
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (WaitUntilPromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
@@ -136,6 +146,7 @@ namespace Cysharp.Threading.Tasks
core.Reset();
predicate = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -153,6 +164,7 @@ namespace Cysharp.Threading.Tasks
Func<bool> predicate;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<object> core;
@@ -160,7 +172,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -174,6 +186,15 @@ namespace Cysharp.Threading.Tasks
result.predicate = predicate;
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (WaitWhilePromise)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -241,6 +262,7 @@ namespace Cysharp.Threading.Tasks
core.Reset();
predicate = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -257,6 +279,7 @@ namespace Cysharp.Threading.Tasks
}
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<object> core;
@@ -264,7 +287,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, out short token)
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, bool completeImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -278,6 +301,15 @@ namespace Cysharp.Threading.Tasks
result.cancellationToken = cancellationToken;
if (completeImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (WaitUntilCanceledPromise)state;
promise.core.TrySetResult(null);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
@@ -329,6 +361,7 @@ namespace Cysharp.Threading.Tasks
TaskTracker.RemoveTracking(this);
core.Reset();
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -351,6 +384,7 @@ namespace Cysharp.Threading.Tasks
Func<T, U> monitorFunction;
IEqualityComparer<U> equalityComparer;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<U> core;
@@ -358,7 +392,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -376,6 +410,15 @@ namespace Cysharp.Threading.Tasks
result.currentValue = monitorFunction(target);
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (WaitUntilValueChangedUnityObjectPromise<T, U>)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -453,6 +496,7 @@ namespace Cysharp.Threading.Tasks
monitorFunction = default;
equalityComparer = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}
@@ -474,6 +518,7 @@ namespace Cysharp.Threading.Tasks
Func<T, U> monitorFunction;
IEqualityComparer<U> equalityComparer;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<U> core;
@@ -481,7 +526,7 @@ namespace Cysharp.Threading.Tasks
{
}
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -498,6 +543,15 @@ namespace Cysharp.Threading.Tasks
result.currentValue = monitorFunction(target);
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (WaitUntilValueChangedStandardObjectPromise<T, U>)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -575,6 +629,7 @@ namespace Cysharp.Threading.Tasks
monitorFunction = default;
equalityComparer = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}

View File

@@ -0,0 +1,122 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks
{
public partial struct UniTask
{
<# for(var i = 2; i <= 15; i++ ) {
var range = Enumerable.Range(1, i);
var t = string.Join(", ", range.Select(x => "T" + x));
var args = string.Join(", ", range.Select(x => $"UniTask<T{x}> task{x}"));
var targs = string.Join(", ", range.Select(x => $"task{x}"));
var tresult = string.Join(", ", range.Select(x => $"task{x}.GetAwaiter().GetResult()"));
var completedSuccessfullyAnd = string.Join(" && ", range.Select(x => $"task{x}.Status.IsCompletedSuccessfully()"));
var tfield = string.Join(", ", range.Select(x => $"self.t{x}"));
#>
public static UniTask<(<#= t #>)> WhenAll<<#= t #>>(<#= args #>)
{
if (<#= completedSuccessfullyAnd #>)
{
return new UniTask<(<#= t #>)>((<#= tresult #>));
}
return new UniTask<(<#= t #>)>(new WhenAllPromise<<#= t #>>(<#= targs #>), 0);
}
sealed class WhenAllPromise<<#= t #>> : IUniTaskSource<(<#= t #>)>
{
<# for(var j = 1; j <= i; j++) { #>
T<#= j #> t<#= j #> = default;
<# } #>
int completedCount;
UniTaskCompletionSourceCore<(<#= t #>)> core;
public WhenAllPromise(<#= args #>)
{
TaskTracker.TrackActiveTask(this, 3);
this.completedCount = 0;
<# for(var j = 1; j <= i; j++) { #>
{
var awaiter = task<#= j #>.GetAwaiter();
if (awaiter.IsCompleted)
{
TryInvokeContinuationT<#= j #>(this, awaiter);
}
else
{
awaiter.SourceOnCompleted(state =>
{
using (var t = (StateTuple<WhenAllPromise<<#= t #>>, UniTask<T<#= j #>>.Awaiter>)state)
{
TryInvokeContinuationT<#= j #>(t.Item1, t.Item2);
}
}, StateTuple.Create(this, awaiter));
}
}
<# } #>
}
<# for(var j = 1; j <= i; j++) { #>
static void TryInvokeContinuationT<#= j #>(WhenAllPromise<<#= t #>> self, in UniTask<T<#= j #>>.Awaiter awaiter)
{
try
{
self.t<#= j #> = awaiter.GetResult();
}
catch (Exception ex)
{
self.core.TrySetException(ex);
return;
}
if (Interlocked.Increment(ref self.completedCount) == <#= i #>)
{
self.core.TrySetResult((<#= tfield #>));
}
}
<# } #>
public (<#= t #>) GetResult(short token)
{
TaskTracker.RemoveTracking(this);
GC.SuppressFinalize(this);
return core.GetResult(token);
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
}
<# } #>
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2c2ecfd98ee1b9a4c9fae1b398c32d75
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,117 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks
{
public partial struct UniTask
{
<# for(var i = 2; i <= 15; i++ ) {
var range = Enumerable.Range(1, i);
var t = string.Join(", ", range.Select(x => "T" + x));
var args = string.Join(", ", range.Select(x => $"UniTask<T{x}> task{x}"));
var targs = string.Join(", ", range.Select(x => $"task{x}"));
var tresult = string.Join(", ", range.Select(x => $"task{x}.GetAwaiter().GetResult()"));
var tBool = string.Join(", ", range.Select(x => $"T{x} result{x}"));
var tfield = string.Join(", ", range.Select(x => $"self.t{x}"));
Func<int, string> getResult = j => string.Join(", ", range.Select(x => (x == j) ? "result" : "default"));
#>
public static UniTask<(int winArgumentIndex, <#= tBool #>)> WhenAny<<#= t #>>(<#= args #>)
{
return new UniTask<(int winArgumentIndex, <#= tBool #>)>(new WhenAnyPromise<<#= t #>>(<#= targs #>), 0);
}
sealed class WhenAnyPromise<<#= t #>> : IUniTaskSource<(int, <#= tBool #>)>
{
int completedCount;
UniTaskCompletionSourceCore<(int, <#= tBool #>)> core;
public WhenAnyPromise(<#= args #>)
{
TaskTracker.TrackActiveTask(this, 3);
this.completedCount = 0;
<# for(var j = 1; j <= i; j++) { #>
{
var awaiter = task<#= j #>.GetAwaiter();
if (awaiter.IsCompleted)
{
TryInvokeContinuationT<#= j #>(this, awaiter);
}
else
{
awaiter.SourceOnCompleted(state =>
{
using (var t = (StateTuple<WhenAnyPromise<<#= t #>>, UniTask<T<#= j #>>.Awaiter>)state)
{
TryInvokeContinuationT<#= j #>(t.Item1, t.Item2);
}
}, StateTuple.Create(this, awaiter));
}
}
<# } #>
}
<# for(var j = 1; j <= i; j++) { #>
static void TryInvokeContinuationT<#= j #>(WhenAnyPromise<<#= t #>> self, in UniTask<T<#= j #>>.Awaiter awaiter)
{
T<#= j #> result;
try
{
result = awaiter.GetResult();
}
catch (Exception ex)
{
self.core.TrySetException(ex);
return;
}
if (Interlocked.Increment(ref self.completedCount) == 1)
{
self.core.TrySetResult((<#= j - 1 #>, <#= getResult(j) #>));
}
}
<# } #>
public (int, <#= tBool #>) GetResult(short token)
{
TaskTracker.RemoveTracking(this);
GC.SuppressFinalize(this);
return core.GetResult(token);
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
}
<# } #>
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 71c2c0bce7543454c8ef545083e18170
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +1,9 @@
{
"name": "UniTask",
"rootNamespace": "",
"references": [],
"references": [
"GUID:e34a5702dd353724aa315fb8011f08c3"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,

View File

@@ -0,0 +1,63 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Collections.Generic;
namespace Cysharp.Threading.Tasks
{
public static partial class UniTaskExtensions
{
// shorthand of WhenAll
public static UniTask.Awaiter GetAwaiter(this UniTask[] tasks)
{
return UniTask.WhenAll(tasks).GetAwaiter();
}
public static UniTask.Awaiter GetAwaiter(this IEnumerable<UniTask> tasks)
{
return UniTask.WhenAll(tasks).GetAwaiter();
}
public static UniTask<T[]>.Awaiter GetAwaiter<T>(this UniTask<T>[] tasks)
{
return UniTask.WhenAll(tasks).GetAwaiter();
}
public static UniTask<T[]>.Awaiter GetAwaiter<T>(this IEnumerable<UniTask<T>> tasks)
{
return UniTask.WhenAll(tasks).GetAwaiter();
}
<# for(var i = 2; i <= 15; i++ ) {
var range = Enumerable.Range(1, i);
var t = string.Join(", ", range.Select(x => "T" + x));
var args = string.Join(", ", range.Select(x => $"UniTask<T{x}> task{x}"));
var titems = string.Join(", ", range.Select(x => $"tasks.Item{x}"));
#>
public static UniTask<(<#= t #>)>.Awaiter GetAwaiter<<#= t #>>(this (<#= args #>) tasks)
{
return UniTask.WhenAll(<#= titems #>).GetAwaiter();
}
<# } #>
<# for(var i = 2; i <= 15; i++ ) {
var range = Enumerable.Range(1, i);
var args = string.Join(", ", range.Select(x => $"UniTask task{x}"));
var titems = string.Join(", ", range.Select(x => $"tasks.Item{x}"));
#>
public static UniTask.Awaiter GetAwaiter(this (<#= args #>) tasks)
{
return UniTask.WhenAll(<#= titems #>).GetAwaiter();
}
<# } #>
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9a75b5d7e55a5a34fb6476586df37c72
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -24,12 +24,17 @@ namespace Cysharp.Threading.Tasks
return AwaitForAllAssets(asyncOperation, null, PlayerLoopTiming.Update, cancellationToken: cancellationToken);
}
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
{
return AwaitForAllAssets(asyncOperation, progress: null, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
@@ -95,15 +100,19 @@ namespace Cysharp.Threading.Tasks
AssetBundleRequest asyncOperation;
IProgress<float> progress;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool completed;
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
Action<AsyncOperation> continuationAction;
AssetBundleRequestAllAssetsConfiguredSource()
{
continuationAction = Continuation;
}
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -118,6 +127,18 @@ namespace Cysharp.Threading.Tasks
result.asyncOperation = asyncOperation;
result.progress = progress;
result.cancellationToken = cancellationToken;
result.completed = false;
asyncOperation.completed += result.continuationAction;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (AssetBundleRequestAllAssetsConfiguredSource)state;
source.core.TrySetCanceled(source.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -161,6 +182,12 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext()
{
// Already completed
if (completed || asyncOperation == null)
{
return false;
}
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
@@ -188,8 +215,29 @@ namespace Cysharp.Threading.Tasks
asyncOperation = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
void Continuation(AsyncOperation _)
{
if (completed)
{
TryReturn();
}
else
{
completed = true;
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
}
else
{
core.TrySetResult(asyncOperation.allAssets);
}
}
}
}
}
}

View File

@@ -20,12 +20,17 @@ namespace Cysharp.Threading.Tasks
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
}
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask<AsyncGPUReadbackRequest> WithCancellation(this AsyncGPUReadbackRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
{
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, out var token), token);
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, cancelImmediately, out var token), token);
}
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
{
static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
@@ -39,15 +44,15 @@ namespace Cysharp.Threading.Tasks
AsyncGPUReadbackRequest asyncOperation;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
AsyncGPUReadbackRequestAwaiterConfiguredSource()
{
}
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -61,6 +66,15 @@ namespace Cysharp.Threading.Tasks
result.asyncOperation = asyncOperation;
result.cancellationToken = cancellationToken;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var promise = (AsyncGPUReadbackRequestAwaiterConfiguredSource)state;
promise.core.TrySetCanceled(promise.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -131,6 +145,7 @@ namespace Cysharp.Threading.Tasks
core.Reset();
asyncOperation = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
}

View File

@@ -17,7 +17,6 @@ namespace Cysharp.Threading.Tasks
#if !UNITY_2023_1_OR_NEWER
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation asyncOperation)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
@@ -30,12 +29,17 @@ namespace Cysharp.Threading.Tasks
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
}
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask WithCancellation(this AsyncOperation asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
{
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
if (asyncOperation.isDone) return UniTask.CompletedTask;
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
public struct AsyncOperationAwaiter : ICriticalNotifyCompletion
@@ -92,15 +96,19 @@ namespace Cysharp.Threading.Tasks
AsyncOperation asyncOperation;
IProgress<float> progress;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool completed;
UniTaskCompletionSourceCore<AsyncUnit> core;
Action<AsyncOperation> continuationAction;
AsyncOperationConfiguredSource()
{
continuationAction = Continuation;
}
public static IUniTaskSource Create(AsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
public static IUniTaskSource Create(AsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -115,6 +123,18 @@ namespace Cysharp.Threading.Tasks
result.asyncOperation = asyncOperation;
result.progress = progress;
result.cancellationToken = cancellationToken;
result.completed = false;
asyncOperation.completed += result.continuationAction;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (AsyncOperationConfiguredSource)state;
source.core.TrySetCanceled(source.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -154,6 +174,12 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext()
{
// Already completed
if (completed || asyncOperation == null)
{
return false;
}
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
@@ -178,11 +204,33 @@ namespace Cysharp.Threading.Tasks
{
TaskTracker.RemoveTracking(this);
core.Reset();
asyncOperation.completed -= continuationAction;
asyncOperation = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
void Continuation(AsyncOperation _)
{
if (completed)
{
TryReturn();
}
else
{
completed = true;
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
}
else
{
core.TrySetResult(AsyncUnit.Default);
}
}
}
}
#endregion
@@ -200,12 +248,17 @@ namespace Cysharp.Threading.Tasks
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
}
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask<UnityEngine.Object> WithCancellation(this ResourceRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
{
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
public struct ResourceRequestAwaiter : ICriticalNotifyCompletion
@@ -266,15 +319,19 @@ namespace Cysharp.Threading.Tasks
ResourceRequest asyncOperation;
IProgress<float> progress;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool completed;
UniTaskCompletionSourceCore<UnityEngine.Object> core;
Action<AsyncOperation> continuationAction;
ResourceRequestConfiguredSource()
{
continuationAction = Continuation;
}
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -289,6 +346,18 @@ namespace Cysharp.Threading.Tasks
result.asyncOperation = asyncOperation;
result.progress = progress;
result.cancellationToken = cancellationToken;
result.completed = false;
asyncOperation.completed += result.continuationAction;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (ResourceRequestConfiguredSource)state;
source.core.TrySetCanceled(source.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -332,6 +401,12 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext()
{
// Already completed
if (completed || asyncOperation == null)
{
return false;
}
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
@@ -356,11 +431,33 @@ namespace Cysharp.Threading.Tasks
{
TaskTracker.RemoveTracking(this);
core.Reset();
asyncOperation.completed -= continuationAction;
asyncOperation = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
void Continuation(AsyncOperation _)
{
if (completed)
{
TryReturn();
}
else
{
completed = true;
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
}
else
{
core.TrySetResult(asyncOperation.asset);
}
}
}
}
#endregion
@@ -379,12 +476,17 @@ namespace Cysharp.Threading.Tasks
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
}
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask<UnityEngine.Object> WithCancellation(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
{
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
public struct AssetBundleRequestAwaiter : ICriticalNotifyCompletion
@@ -445,15 +547,19 @@ namespace Cysharp.Threading.Tasks
AssetBundleRequest asyncOperation;
IProgress<float> progress;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool completed;
UniTaskCompletionSourceCore<UnityEngine.Object> core;
Action<AsyncOperation> continuationAction;
AssetBundleRequestConfiguredSource()
{
continuationAction = Continuation;
}
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -468,6 +574,18 @@ namespace Cysharp.Threading.Tasks
result.asyncOperation = asyncOperation;
result.progress = progress;
result.cancellationToken = cancellationToken;
result.completed = false;
asyncOperation.completed += result.continuationAction;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (AssetBundleRequestConfiguredSource)state;
source.core.TrySetCanceled(source.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -511,6 +629,12 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext()
{
// Already completed
if (completed || asyncOperation == null)
{
return false;
}
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
@@ -535,11 +659,33 @@ namespace Cysharp.Threading.Tasks
{
TaskTracker.RemoveTracking(this);
core.Reset();
asyncOperation.completed -= continuationAction;
asyncOperation = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
void Continuation(AsyncOperation _)
{
if (completed)
{
TryReturn();
}
else
{
completed = true;
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
}
else
{
core.TrySetResult(asyncOperation.asset);
}
}
}
}
#endregion
@@ -559,12 +705,17 @@ namespace Cysharp.Threading.Tasks
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
}
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask<AssetBundle> WithCancellation(this AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
{
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<AssetBundle>(cancellationToken);
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
public struct AssetBundleCreateRequestAwaiter : ICriticalNotifyCompletion
@@ -625,15 +776,19 @@ namespace Cysharp.Threading.Tasks
AssetBundleCreateRequest asyncOperation;
IProgress<float> progress;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool completed;
UniTaskCompletionSourceCore<AssetBundle> core;
Action<AsyncOperation> continuationAction;
AssetBundleCreateRequestConfiguredSource()
{
continuationAction = Continuation;
}
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -648,6 +803,18 @@ namespace Cysharp.Threading.Tasks
result.asyncOperation = asyncOperation;
result.progress = progress;
result.cancellationToken = cancellationToken;
result.completed = false;
asyncOperation.completed += result.continuationAction;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (AssetBundleCreateRequestConfiguredSource)state;
source.core.TrySetCanceled(source.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -691,6 +858,12 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext()
{
// Already completed
if (completed || asyncOperation == null)
{
return false;
}
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
@@ -715,11 +888,33 @@ namespace Cysharp.Threading.Tasks
{
TaskTracker.RemoveTracking(this);
core.Reset();
asyncOperation.completed -= continuationAction;
asyncOperation = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
void Continuation(AsyncOperation _)
{
if (completed)
{
TryReturn();
}
else
{
completed = true;
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
}
else
{
core.TrySetResult(asyncOperation.assetBundle);
}
}
}
}
#endregion
@@ -739,7 +934,12 @@ namespace Cysharp.Threading.Tasks
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
}
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask<UnityWebRequest> WithCancellation(this UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
{
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityWebRequest>(cancellationToken);
@@ -751,7 +951,7 @@ namespace Cysharp.Threading.Tasks
}
return UniTask.FromResult(asyncOperation.webRequest);
}
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
public struct UnityWebRequestAsyncOperationAwaiter : ICriticalNotifyCompletion
@@ -820,15 +1020,19 @@ namespace Cysharp.Threading.Tasks
UnityWebRequestAsyncOperation asyncOperation;
IProgress<float> progress;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool completed;
UniTaskCompletionSourceCore<UnityWebRequest> core;
Action<AsyncOperation> continuationAction;
UnityWebRequestAsyncOperationConfiguredSource()
{
continuationAction = Continuation;
}
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -843,6 +1047,19 @@ namespace Cysharp.Threading.Tasks
result.asyncOperation = asyncOperation;
result.progress = progress;
result.cancellationToken = cancellationToken;
result.completed = false;
asyncOperation.completed += result.continuationAction;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (UnityWebRequestAsyncOperationConfiguredSource)state;
source.asyncOperation.webRequest.Abort();
source.core.TrySetCanceled(source.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
@@ -886,6 +1103,12 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext()
{
// Already completed
if (completed || asyncOperation == null)
{
return false;
}
if (cancellationToken.IsCancellationRequested)
{
asyncOperation.webRequest.Abort();
@@ -900,11 +1123,7 @@ namespace Cysharp.Threading.Tasks
if (asyncOperation.isDone)
{
if (asyncOperation.webRequest == null)
{
core.TrySetException(new ObjectDisposedException("The webRequest has been destroyed."));
}
else if (asyncOperation.webRequest.IsError())
if (asyncOperation.webRequest.IsError())
{
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
}
@@ -922,11 +1141,37 @@ namespace Cysharp.Threading.Tasks
{
TaskTracker.RemoveTracking(this);
core.Reset();
asyncOperation.completed -= continuationAction;
asyncOperation = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
void Continuation(AsyncOperation _)
{
if (completed)
{
TryReturn();
}
else
{
completed = true;
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
}
else if (asyncOperation.webRequest.IsError())
{
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
}
else
{
core.TrySetResult(asyncOperation.webRequest);
}
}
}
}
#endregion

View File

@@ -0,0 +1,349 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var types = new (string typeName, string returnType, string returnField)[]
{
("AsyncOperation", "void", null),
("ResourceRequest", "UnityEngine.Object", "asset"),
("AssetBundleRequest", "UnityEngine.Object", "asset"), // allAssets?
("AssetBundleCreateRequest", "AssetBundle", "assetBundle"),
("UnityWebRequestAsyncOperation", "UnityWebRequest", "webRequest") // -> #if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
};
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
Func<(string typeName, string returnType, string returnField), bool> IsAsyncOperationBase = x => x.typeName == "AsyncOperation";
Func<(string typeName, string returnType, string returnField), bool> IsUnityWebRequest = x => x.returnType == "UnityWebRequest";
Func<(string typeName, string returnType, string returnField), bool> IsAssetBundleModule = x => x.typeName == "AssetBundleRequest" || x.typeName == "AssetBundleCreateRequest";
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
#>
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using UnityEngine;
using Cysharp.Threading.Tasks.Internal;
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
using UnityEngine.Networking;
#endif
namespace Cysharp.Threading.Tasks
{
public static partial class UnityAsyncExtensions
{
<# foreach(var t in types) { #>
<# if(IsUnityWebRequest(t)) { #>
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
<# } else if(IsAssetBundleModule(t)) { #>
#if UNITASK_ASSETBUNDLE_SUPPORT
<# } #>
#region <#= t.typeName #>
<# if (IsAsyncOperationBase(t)) { #>
#if !UNITY_2023_1_OR_NEWER
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
<# } #>
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
return new <#= t.typeName #>Awaiter(asyncOperation);
}
<# if (IsAsyncOperationBase(t)) { #>
#endif
<# } #>
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
{
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
}
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
{
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
}
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
<# if(IsUnityWebRequest(t)) { #>
if (asyncOperation.isDone)
{
if (asyncOperation.webRequest.IsError())
{
return UniTask.FromException<UnityWebRequest>(new UnityWebRequestException(asyncOperation.webRequest));
}
return UniTask.FromResult(asyncOperation.webRequest);
}
<# } else { #>
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
<# } #>
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
}
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
{
<#= t.typeName #> asyncOperation;
Action<AsyncOperation> continuationAction;
public <#= t.typeName #>Awaiter(<#= t.typeName #> asyncOperation)
{
this.asyncOperation = asyncOperation;
this.continuationAction = null;
}
public bool IsCompleted => asyncOperation.isDone;
public <#= t.returnType #> GetResult()
{
if (continuationAction != null)
{
asyncOperation.completed -= continuationAction;
continuationAction = null;
<# if (!IsVoid(t)) { #>
var result = <#= $"asyncOperation.{t.returnField}" #>;
asyncOperation = null;
<# if(IsUnityWebRequest(t)) { #>
if (result.IsError())
{
throw new UnityWebRequestException(result);
}
<# } #>
return result;
<# } else { #>
asyncOperation = null;
<# } #>
}
else
{
<# if (!IsVoid(t)) { #>
var result = <#= $"asyncOperation.{t.returnField}" #>;
asyncOperation = null;
<# if(IsUnityWebRequest(t)) { #>
if (result.IsError())
{
throw new UnityWebRequestException(result);
}
<# } #>
return result;
<# } else { #>
asyncOperation = null;
<# } #>
}
}
public void OnCompleted(Action continuation)
{
UnsafeOnCompleted(continuation);
}
public void UnsafeOnCompleted(Action continuation)
{
Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
continuationAction = PooledDelegate<AsyncOperation>.Create(continuation);
asyncOperation.completed += continuationAction;
}
}
sealed class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>ConfiguredSource>
{
static TaskPool<<#= t.typeName #>ConfiguredSource> pool;
<#= t.typeName #>ConfiguredSource nextNode;
public ref <#= t.typeName #>ConfiguredSource NextNode => ref nextNode;
static <#= t.typeName #>ConfiguredSource()
{
TaskPool.RegisterSizeGetter(typeof(<#= t.typeName #>ConfiguredSource), () => pool.Size);
}
<#= t.typeName #> asyncOperation;
IProgress<float> progress;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool completed;
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
Action<AsyncOperation> continuationAction;
<#= t.typeName #>ConfiguredSource()
{
continuationAction = Continuation;
}
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
return AutoResetUniTaskCompletionSource<#= IsVoid(t) ? "" : $"<{t.returnType}>" #>.CreateFromCanceled(cancellationToken, out token);
}
if (!pool.TryPop(out var result))
{
result = new <#= t.typeName #>ConfiguredSource();
}
result.asyncOperation = asyncOperation;
result.progress = progress;
result.cancellationToken = cancellationToken;
result.completed = false;
asyncOperation.completed += result.continuationAction;
if (cancelImmediately && cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
{
var source = (<#= t.typeName #>ConfiguredSource)state;
<# if(IsUnityWebRequest(t)) { #>
source.asyncOperation.webRequest.Abort();
<# } #>
source.core.TrySetCanceled(source.cancellationToken);
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
token = result.core.Version;
return result;
}
public <#= t.returnType #> GetResult(short token)
{
try
{
<# if (!IsVoid(t)) { #>
return core.GetResult(token);
<# } else { #>
core.GetResult(token);
<# } #>
}
finally
{
TryReturn();
}
}
<# if (!IsVoid(t)) { #>
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
<# } #>
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public bool MoveNext()
{
// Already completed
if (completed || asyncOperation == null)
{
return false;
}
if (cancellationToken.IsCancellationRequested)
{
<# if(IsUnityWebRequest(t)) { #>
asyncOperation.webRequest.Abort();
<# } #>
core.TrySetCanceled(cancellationToken);
return false;
}
if (progress != null)
{
progress.Report(asyncOperation.progress);
}
if (asyncOperation.isDone)
{
<# if(IsUnityWebRequest(t)) { #>
if (asyncOperation.webRequest.IsError())
{
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
}
else
{
core.TrySetResult(asyncOperation.webRequest);
}
<# } else { #>
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
<# } #>
return false;
}
return true;
}
bool TryReturn()
{
TaskTracker.RemoveTracking(this);
core.Reset();
asyncOperation.completed -= continuationAction;
asyncOperation = default;
progress = default;
cancellationToken = default;
cancellationTokenRegistration.Dispose();
return pool.TryPush(this);
}
void Continuation(AsyncOperation _)
{
if (completed)
{
TryReturn();
}
else
{
completed = true;
if (cancellationToken.IsCancellationRequested)
{
core.TrySetCanceled(cancellationToken);
}
<# if(IsUnityWebRequest(t)) { #>
else if (asyncOperation.webRequest.IsError())
{
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
}
else
{
core.TrySetResult(asyncOperation.webRequest);
}
<# } else { #>
else
{
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
}
<# } #>
}
}
}
#endregion
<# if(IsUnityWebRequest(t) || IsAssetBundleModule(t)) { #>
#endif
<# } #>
<# } #>
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b1053c85b3f0794488b10e6de53e9c02
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
#if UNITY_2023_1_OR_NEWER
namespace Cysharp.Threading.Tasks
{
public static class UnityAwaitableExtensions
{
public static async UniTask AsUniTask(this UnityEngine.Awaitable awaitable)
{
await awaitable;
}
public static async UniTask<T> AsUniTask<T>(this UnityEngine.Awaitable<T> awaitable)
{
return await awaitable;
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c29533c9e4284dee914b71a6579ea274
timeCreated: 1698895807

View File

@@ -3,4 +3,5 @@
[assembly: InternalsVisibleTo("UniTask.Linq")]
[assembly: InternalsVisibleTo("UniTask.Addressables")]
[assembly: InternalsVisibleTo("UniTask.DOTween")]
[assembly: InternalsVisibleTo("UniTask.TextMeshPro")]
[assembly: InternalsVisibleTo("UniTask.TextMeshPro")]
[assembly: InternalsVisibleTo("UniTask.YooAsset")]

View File

@@ -2,7 +2,7 @@
"name": "com.cysharp.unitask",
"displayName": "UniTask",
"author": { "name": "Cysharp, Inc.", "url": "https://cysharp.co.jp/en/" },
"version": "2.4.0",
"version": "2.5.0",
"unity": "2018.4",
"description": "Provides an efficient async/await integration to Unity.",
"keywords": [ "async/await", "async", "Task", "UniTask" ],