master
neuecc 2020-05-12 16:09:34 +09:00
parent f6622ad29c
commit 6a5e259006
4 changed files with 239 additions and 351 deletions

View File

@ -1,275 +0,0 @@
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
{
return new Timer(dueTime, null, updateTiming, ignoreTimeScale);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
{
return new Timer(dueTime, period, updateTiming, ignoreTimeScale);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
{
return new Timer(period, period, updateTiming, ignoreTimeScale);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
{
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
{
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
}
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
{
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
}
}
internal class Timer : IUniTaskAsyncEnumerable<AsyncUnit>
{
readonly PlayerLoopTiming updateTiming;
readonly TimeSpan dueTime;
readonly TimeSpan? period;
readonly bool ignoreTimeScale;
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale)
{
this.updateTiming = updateTiming;
this.dueTime = dueTime;
this.period = period;
this.ignoreTimeScale = ignoreTimeScale;
}
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken);
}
class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
{
readonly float dueTime;
readonly float? period;
readonly PlayerLoopTiming updateTiming;
readonly bool ignoreTimeScale;
CancellationToken cancellationToken;
float elapsed;
bool dueTimePhase;
bool disposed;
public Enumerator(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken)
{
this.dueTime = (float)dueTime.TotalSeconds;
this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
if (this.dueTime <= 0) this.dueTime = 0;
if (this.period != null)
{
if (this.period <= 0) this.period = 1;
}
this.dueTimePhase = true;
this.updateTiming = updateTiming;
this.ignoreTimeScale = ignoreTimeScale;
TaskTracker.TrackActiveTask(this, 2);
PlayerLoopHelper.AddAction(updateTiming, this);
}
public AsyncUnit Current => default;
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
public UniTask DisposeAsync()
{
if (!disposed)
{
disposed = true;
TaskTracker.RemoveTracking(this);
}
return default;
}
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested)
{
completionSource.TrySetResult(false);
return false;
}
AddElapsed();
if (dueTimePhase)
{
if (elapsed >= dueTime)
{
dueTimePhase = false;
elapsed = 0;
completionSource.TrySetResult(true);
}
}
else
{
if (period == null)
{
completionSource.TrySetResult(false);
return false;
}
if (elapsed >= period)
{
elapsed = 0;
completionSource.TrySetResult(true);
}
}
return true;
}
void AddElapsed()
{
if (updateTiming == PlayerLoopTiming.FixedUpdate)
{
if (ignoreTimeScale)
{
elapsed += UnityEngine.Time.fixedUnscaledDeltaTime;
}
else
{
elapsed += UnityEngine.Time.fixedDeltaTime;
}
}
else
{
if (ignoreTimeScale)
{
elapsed += UnityEngine.Time.unscaledDeltaTime;
}
else
{
elapsed += UnityEngine.Time.deltaTime;
}
}
}
}
}
internal class TimerFrame : IUniTaskAsyncEnumerable<AsyncUnit>
{
readonly PlayerLoopTiming updateTiming;
readonly int dueTimeFrameCount;
readonly int? periodFrameCount;
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming)
{
this.updateTiming = updateTiming;
this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount;
}
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken);
}
class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
{
readonly int dueTimeFrameCount;
readonly int? periodFrameCount;
CancellationToken cancellationToken;
int currentFrame;
bool dueTimePhase;
bool disposed;
public Enumerator(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
{
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
if (periodFrameCount != null)
{
if (periodFrameCount <= 0) periodFrameCount = 1;
}
this.dueTimePhase = true;
this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount;
TaskTracker.TrackActiveTask(this, 2);
PlayerLoopHelper.AddAction(updateTiming, this);
}
public AsyncUnit Current => default;
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
public UniTask DisposeAsync()
{
if (!disposed)
{
disposed = true;
TaskTracker.RemoveTracking(this);
}
return default;
}
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested)
{
completionSource.TrySetResult(false);
return false;
}
if (dueTimePhase)
{
if (currentFrame++ == dueTimeFrameCount)
{
dueTimePhase = false;
completionSource.TrySetResult(true);
currentFrame = -1;
}
}
else
{
if (periodFrameCount == null)
{
completionSource.TrySetResult(false);
return false;
}
if (++currentFrame == periodFrameCount)
{
completionSource.TrySetResult(true);
currentFrame = 0;
}
}
return true;
}
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 14e8116614488eb43b1428191cef8fe5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,76 +1,249 @@
//using Cysharp.Threading.Tasks.Internal; using System;
//using System; using System.Threading;
//using System.Collections.Generic;
//using System.Threading;
//namespace Cysharp.Threading.Tasks.Linq namespace Cysharp.Threading.Tasks.Linq
//{ {
// public static partial class UniTaskAsyncEnumerable public static partial class UniTaskAsyncEnumerable
// { {
// public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update) public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
// { {
// return new EveryUpdate(updateTiming); return new Timer(dueTime, null, updateTiming, ignoreTimeScale);
// } }
// }
// internal class EveryUpdate : IUniTaskAsyncEnumerable<AsyncUnit> public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
// { {
// readonly PlayerLoopTiming updateTiming; return new Timer(dueTime, period, updateTiming, ignoreTimeScale);
}
// public EveryUpdate(PlayerLoopTiming updateTiming) public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
// { {
// this.updateTiming = updateTiming; return new Timer(period, period, updateTiming, ignoreTimeScale);
// } }
// public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default) public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
// { {
// return new Enumerator(updateTiming, cancellationToken); return new TimerFrame(dueTimeFrameCount, null, updateTiming);
// } }
// class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
// { {
// readonly PlayerLoopTiming updateTiming; return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
// CancellationToken cancellationToken; }
// bool disposed; public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
{
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
}
}
// public Enumerator(PlayerLoopTiming updateTiming, CancellationToken cancellationToken) internal class Timer : IUniTaskAsyncEnumerable<AsyncUnit>
// { {
// this.updateTiming = updateTiming; readonly PlayerLoopTiming updateTiming;
readonly TimeSpan dueTime;
readonly TimeSpan? period;
readonly bool ignoreTimeScale;
// TaskTracker.TrackActiveTask(this, 2); public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale)
// PlayerLoopHelper.AddAction(updateTiming, this); {
// } this.updateTiming = updateTiming;
this.dueTime = dueTime;
this.period = period;
this.ignoreTimeScale = ignoreTimeScale;
}
// public AsyncUnit Current => default; public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken);
}
// public UniTask<bool> MoveNextAsync() class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
// { {
// return false instead of throw readonly float dueTime;
// if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False; readonly float? period;
readonly PlayerLoopTiming updateTiming;
readonly bool ignoreTimeScale;
CancellationToken cancellationToken;
// completionSource.Reset(); float elapsed;
// return new UniTask<bool>(this, completionSource.Version); bool dueTimePhase;
// } bool disposed;
// public UniTask DisposeAsync() public Enumerator(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken)
// { {
// if (!disposed) this.dueTime = (float)dueTime.TotalSeconds;
// { this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
// disposed = true;
// TaskTracker.RemoveTracking(this);
// }
// return default;
// }
// public bool MoveNext() if (this.dueTime <= 0) this.dueTime = 0;
// { if (this.period != null)
// if (disposed) return false; {
// if (cancellationToken.IsCancellationRequested) return false; if (this.period <= 0) this.period = 1;
}
// completionSource.TrySetResult(true); this.dueTimePhase = true;
// return true; this.updateTiming = updateTiming;
// } this.ignoreTimeScale = ignoreTimeScale;
// } TaskTracker.TrackActiveTask(this, 2);
// } PlayerLoopHelper.AddAction(updateTiming, this);
//} }
public AsyncUnit Current => default;
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
public UniTask DisposeAsync()
{
if (!disposed)
{
disposed = true;
TaskTracker.RemoveTracking(this);
}
return default;
}
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested)
{
completionSource.TrySetResult(false);
return false;
}
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
if (dueTimePhase)
{
if (elapsed >= dueTime)
{
dueTimePhase = false;
elapsed = 0;
completionSource.TrySetResult(true);
}
}
else
{
if (period == null)
{
completionSource.TrySetResult(false);
return false;
}
if (elapsed >= period)
{
elapsed = 0;
completionSource.TrySetResult(true);
}
}
return true;
}
}
}
internal class TimerFrame : IUniTaskAsyncEnumerable<AsyncUnit>
{
readonly PlayerLoopTiming updateTiming;
readonly int dueTimeFrameCount;
readonly int? periodFrameCount;
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming)
{
this.updateTiming = updateTiming;
this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount;
}
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken);
}
class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
{
readonly int dueTimeFrameCount;
readonly int? periodFrameCount;
CancellationToken cancellationToken;
int currentFrame;
bool dueTimePhase;
bool disposed;
public Enumerator(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
{
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
if (periodFrameCount != null)
{
if (periodFrameCount <= 0) periodFrameCount = 1;
}
this.dueTimePhase = true;
this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount;
TaskTracker.TrackActiveTask(this, 2);
PlayerLoopHelper.AddAction(updateTiming, this);
}
public AsyncUnit Current => default;
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
public UniTask DisposeAsync()
{
if (!disposed)
{
disposed = true;
TaskTracker.RemoveTracking(this);
}
return default;
}
public bool MoveNext()
{
if (disposed || cancellationToken.IsCancellationRequested)
{
completionSource.TrySetResult(false);
return false;
}
if (dueTimePhase)
{
if (currentFrame++ == dueTimeFrameCount)
{
dueTimePhase = false;
completionSource.TrySetResult(true);
currentFrame = 0;
}
}
else
{
if (periodFrameCount == null)
{
completionSource.TrySetResult(false);
return false;
}
if (++currentFrame == periodFrameCount)
{
completionSource.TrySetResult(true);
currentFrame = 0;
}
}
return true;
}
}
}
}

View File

@ -146,11 +146,12 @@ public class SandboxMain : MonoBehaviour
//StartCoroutine(cor); //StartCoroutine(cor);
Debug.Log("E:" + DateTime.Now.ToString()); // await UniTask.Yield(PlayerLoopTiming.EarlyUpdate);
Debug.Log("Start:" + Time.frameCount);
await UniTaskAsyncEnumerable.Timer(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5), PlayerLoopTiming.Update).ForEachAsync(_ => await UniTaskAsyncEnumerable.TimerFrame(3, 5, PlayerLoopTiming.LastPostLateUpdate).ForEachAsync(_ =>
{ {
Debug.Log("Call:" + DateTime.Now.ToString()); Debug.Log("Call:" + Time.frameCount);
}, cancellationToken: this.GetCancellationTokenOnDestroy()); }, cancellationToken: this.GetCancellationTokenOnDestroy());
//try //try