This commit is contained in:
ousttrue
2021-02-18 19:47:04 +09:00
parent c3997af90e
commit 92ced5ea89
3 changed files with 101 additions and 67 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@@ -28,11 +29,74 @@ namespace UniGLTF.ExplicitTask
IAwaiter<T> GetAwaiter();
}
public delegate void EnequeueCallback(Action continuation);
public class TaskQueue : IDisposable
{
[ThreadStatic]
static EnequeueCallback s_EnequeueCallback;
public static void EnequeueCurrent(Action continuation)
{
if (s_EnequeueCallback == null)
{
System.Threading.SynchronizationContext.Current.Post(_ =>
{
continuation();
}, null);
}
else
{
s_EnequeueCallback(continuation);
}
}
EnequeueCallback m_backup;
Queue<Action> m_tasks = new Queue<Action>();
public static TaskQueue Create()
{
return new TaskQueue();
}
TaskQueue()
{
m_backup = s_EnequeueCallback;
s_EnequeueCallback = x =>
{
m_tasks.Enqueue(x);
};
}
public void Dispose()
{
s_EnequeueCallback = m_backup;
}
public bool ExecuteOneCallback()
{
if (m_tasks.Count == 0)
{
return false;
}
var task = m_tasks.Dequeue();
task();
return true;
}
}
public class Awaiter<T> : IAwaiter<T>
{
Task<T> m_task;
public bool IsCompleted => m_task.IsCompleted;
public bool IsCompleted
{
get
{
return m_task.IsCompleted;
}
}
public T GetResult()
{
@@ -41,7 +105,7 @@ namespace UniGLTF.ExplicitTask
public void OnCompleted(Action continuation)
{
continuation();
TaskQueue.EnequeueCurrent(continuation);
}
public Awaiter(Task<T> task)
@@ -114,6 +178,29 @@ namespace UniGLTF.ExplicitTask
{
return new Awaiter<T>(_task);
}
public bool IsCompleted => _task.IsCompleted;
}
public struct ThreadTask
{
public static ExplicitTask<T> RunThreadAsync<T>(Func<T> callback)
{
var tcs = new TaskCompletionSource<T>();
System.Threading.ThreadPool.QueueUserWorkItem(_ =>
{
try
{
var t = callback();
tcs.SetResult(t);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
});
return new ExplicitTask<T>(tcs.Task);
}
}
public struct Unit { }

View File

@@ -383,7 +383,7 @@ namespace UniGLTF
var index = i;
using (MeasureTime("ReadMesh"))
{
var x = meshImporter.ReadMesh(this, index);
var x= meshImporter.ReadMesh(this, index);
var y = await BuildMeshAsync(nextFrame, x, index);
Meshes.Add(y);
}

View File

@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using UniGLTF.ExplicitTask;
namespace UniGLTF
{
@@ -29,73 +27,22 @@ namespace UniGLTF
self.Root.name = Path.GetFileNameWithoutExtension(path);
}
// class TemporarySynchronizationContext : SynchronizationContext
// {
// Queue<Action> m_callbacks = new Queue<Action>();
// /// <summary>
// /// await して中断された継続がここにくる。
// ///
// /// ex. await Task.Run(() =>{ /* ここ */ });
// /// </summary>
// /// <param name="d"></param>
// /// <param name="state"></param>
// public override void Post(SendOrPostCallback d, object state)
// {
// // Debug.Log($"Post");
// m_callbacks.Enqueue(() => d(state));
// }
// /// <summary>
// /// 一個デキューして実行する。
// /// Unityであれば毎フレームこのように消化しているであろう。
// ///
// /// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Scripting/UnitySynchronizationContext.cs
// /// </summary>
// /// <returns></returns>
// public bool ExecuteOneCallback()
// {
// while (m_callbacks.Count == 0)
// {
// // Debug.Log($"empty callbacks");
// return false;
// }
// var callback = m_callbacks.Dequeue();
// callback();
// return true;
// }
// }
/// <summary>
/// Build unity objects from parsed gltf
/// </summary>
public static void Load(this ImporterContext self)
{
throw new NotImplementedException();
using (var queue = TaskQueue.Create())
{
var task = self.LoadAsync();
// var tcs = new TemporarySynchronizationContext();
// // 元に戻すためバックアップ
// var backup = SynchronizationContext.Current;
// // 一時的に変更
// SynchronizationContext.SetSynchronizationContext(tcs);
// try
// {
// var task = self.LoadAsync();
// // 中断された await を消化する
// while (!task.IsCompleted)
// {
// // execute synchronous
// tcs.ExecuteOneCallback();
// }
// }
// finally
// {
// // 元に戻す
// SynchronizationContext.SetSynchronizationContext(backup);
// }
// 中断された await を消化する
while (!task.IsCompleted)
{
// execute synchronous
queue.ExecuteOneCallback();
}
}
}
}
}