RuntimeOnlyAwaitCaller を実装

This commit is contained in:
Masataka SUMI 2021-10-14 19:18:44 +09:00
parent 4743ad7c57
commit cb1e30a195
6 changed files with 132 additions and 0 deletions

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using Object = UnityEngine.Object;
namespace VRMShaders
{
public sealed class NextFrameTaskScheduler
{
public bool IsSupported => Application.isPlaying;
public NextFrameTaskScheduler()
{
if (!IsSupported)
{
throw new NotSupportedException($"{nameof(NextFrameTaskScheduler)} is supported at runtime only.");
}
}
public bool Enqueue(Action action)
{
var currentFrame = Time.frameCount;
UnityLoopTaskScheduler.Instance.Scheduler.Enqueue(action, () => Time.frameCount != currentFrame);
return true;
}
private sealed class UnityLoopTaskScheduler : MonoBehaviour
{
private static UnityLoopTaskScheduler _instance;
public static UnityLoopTaskScheduler Instance
{
get
{
if (_instance == null)
{
var go = new GameObject("UniGLTF UnityThreadScheduler");
Object.DontDestroyOnLoad(go);
_instance = go.AddComponent<UnityLoopTaskScheduler>();
}
return _instance;
}
}
public TinyManagedTaskScheduler Scheduler { get; } = new TinyManagedTaskScheduler();
private void Update()
{
Scheduler.ManagedUpdate();
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3ce7defdc7144878a058274ae561d0be
timeCreated: 1634203513

View File

@ -0,0 +1,32 @@
using System;
using System.Threading.Tasks;
namespace VRMShaders
{
public sealed class RuntimeOnlyAwaitCaller : IAwaitCaller
{
private readonly NextFrameTaskScheduler _scheduler;
public RuntimeOnlyAwaitCaller()
{
_scheduler = new NextFrameTaskScheduler();
}
public Task NextFrame()
{
var tcs = new TaskCompletionSource<object>();
_scheduler.Enqueue(() => tcs.SetResult(default));
return tcs.Task;
}
public Task Run(Action action)
{
return Task.Run(action);
}
public Task<T> Run<T>(Func<T> action)
{
return Task.Run(action);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e4e64b1835ca4cd2b682a6bda572b8fb
timeCreated: 1634203216

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using UnityEngine;
namespace VRMShaders
{
internal sealed class TinyManagedTaskScheduler
{
private readonly ConcurrentQueue<(Action, Func<bool>)> _continuationQueue =
new ConcurrentQueue<(Action, Func<bool>)>();
public void ManagedUpdate()
{
while (_continuationQueue.TryDequeue(out var tuple))
{
var (continuation, canExecute) = tuple;
if (canExecute())
{
continuation();
}
else
{
_continuationQueue.Enqueue(tuple);
}
}
}
public void Enqueue(Action continuation, Func<bool> canExecute)
{
_continuationQueue.Enqueue((continuation, canExecute));
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9c52ff07a0834bdc8f4c8d6c7f9a634f
timeCreated: 1634203919