Merge pull request #1781 from matsutaka-pxv/iawaitcaller-nextframe-iftimedout

BREAKING CHANGE: Add interface method IAwaitCaller.NextFrameIfTimedOut which invokes NextFrame if timed out
This commit is contained in:
Masataka SUMI 2022-09-08 18:05:59 +09:00 committed by GitHub
commit 2f7ea945bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 3 deletions

View File

@ -31,5 +31,11 @@ namespace VRMShaders
/// <typeparam name="T"></typeparam>
/// <returns></returns>
Task<T> Run<T>(Func<T> action);
/// <summary>
/// 指定した時間が経過している場合のみ、NextFrame() を使って1フレーム待つ
/// </summary>
/// <returns>タイムアウト時はNextFrame()を呼び出す。そうではない場合、Task.CompletedTaskを返す</returns>
Task NextFrameIfTimedOut();
}
}

View File

@ -23,5 +23,7 @@ namespace VRMShaders
{
return Task.FromResult(action());
}
public Task NextFrameIfTimedOut() => NextFrame();
}
}

View File

@ -10,14 +10,23 @@ namespace VRMShaders
public sealed class RuntimeOnlyAwaitCaller : IAwaitCaller
{
private readonly NextFrameTaskScheduler _scheduler;
private readonly float _timeOutInSeconds;
private float _lastTimeoutBaseTime;
public RuntimeOnlyAwaitCaller()
/// <summary>
/// タイムアウト指定可能なコンストラクタ
/// </summary>
/// <param name="timeOutInSeconds">NextFrameIfTimedOutがタイムアウトと見なす時間(秒単位)</param>
public RuntimeOnlyAwaitCaller(float timeOutInSeconds = 1f / 1000f)
{
_scheduler = new NextFrameTaskScheduler();
_timeOutInSeconds = timeOutInSeconds;
ResetLastTimeoutBaseTime();
}
public Task NextFrame()
{
ResetLastTimeoutBaseTime();
var tcs = new TaskCompletionSource<object>();
_scheduler.Enqueue(() => tcs.SetResult(default));
return tcs.Task;
@ -32,5 +41,21 @@ namespace VRMShaders
{
return Task.Run(action);
}
public Task NextFrameIfTimedOut() => CheckTimeout() ? NextFrame() : Task.CompletedTask;
private void ResetLastTimeoutBaseTime() => _lastTimeoutBaseTime = 0f;
private bool LastTimeoutBaseTimeNeedsReset => _lastTimeoutBaseTime == 0f;
private bool CheckTimeout()
{
float t = UnityEngine.Time.realtimeSinceStartup;
if (LastTimeoutBaseTimeNeedsReset)
{
_lastTimeoutBaseTime = t;
}
return (t - _lastTimeoutBaseTime) >= _timeOutInSeconds;
}
}
}
}

View File

@ -10,14 +10,23 @@ namespace VRMShaders
public sealed class RuntimeOnlyNoThreadAwaitCaller : IAwaitCaller
{
private readonly NextFrameTaskScheduler _scheduler;
private readonly float _timeoutInSeconds;
private float _lastTimeoutBaseTime;
public RuntimeOnlyNoThreadAwaitCaller()
/// <summary>
/// タイムアウト指定可能なコンストラクタ
/// </summary>
/// <param name="timeoutInSeconds">NextFrameIfTimedOutがタイムアウトと見なす時間(秒単位)</param>
public RuntimeOnlyNoThreadAwaitCaller(float timeoutInSeconds = 1f / 1000f)
{
_scheduler = new NextFrameTaskScheduler();
_timeoutInSeconds = timeoutInSeconds;
ResetLastTimeoutBaseTime();
}
public Task NextFrame()
{
ResetLastTimeoutBaseTime();
var tcs = new TaskCompletionSource<object>();
_scheduler.Enqueue(() => tcs.SetResult(default));
return tcs.Task;
@ -47,5 +56,21 @@ namespace VRMShaders
return Task.FromException<T>(ex);
}
}
public Task NextFrameIfTimedOut() => CheckTimeout() ? NextFrame() : Task.CompletedTask;
private void ResetLastTimeoutBaseTime() => _lastTimeoutBaseTime = 0f;
private bool LastTimeoutBaseTimeNeedsReset => _lastTimeoutBaseTime == 0f;
private bool CheckTimeout()
{
float t = UnityEngine.Time.realtimeSinceStartup;
if (LastTimeoutBaseTimeNeedsReset)
{
_lastTimeoutBaseTime = t;
}
return (t - _lastTimeoutBaseTime) >= _timeoutInSeconds;
}
}
}