95 lines
2.3 KiB
C#
95 lines
2.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Godot
|
|
{
|
|
public class GodotTaskScheduler : TaskScheduler
|
|
{
|
|
private GodotSynchronizationContext Context { get; set; }
|
|
private readonly LinkedList<Task> _tasks = new LinkedList<Task>();
|
|
|
|
public GodotTaskScheduler()
|
|
{
|
|
Context = new GodotSynchronizationContext();
|
|
SynchronizationContext.SetSynchronizationContext(Context);
|
|
}
|
|
|
|
protected sealed override void QueueTask(Task task)
|
|
{
|
|
lock (_tasks)
|
|
{
|
|
_tasks.AddLast(task);
|
|
}
|
|
}
|
|
|
|
protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
|
|
{
|
|
if (SynchronizationContext.Current != Context)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (taskWasPreviouslyQueued)
|
|
{
|
|
TryDequeue(task);
|
|
}
|
|
|
|
return TryExecuteTask(task);
|
|
}
|
|
|
|
protected sealed override bool TryDequeue(Task task)
|
|
{
|
|
lock (_tasks)
|
|
{
|
|
return _tasks.Remove(task);
|
|
}
|
|
}
|
|
|
|
protected sealed override IEnumerable<Task> GetScheduledTasks()
|
|
{
|
|
lock (_tasks)
|
|
{
|
|
return _tasks.ToArray();
|
|
}
|
|
}
|
|
|
|
public void Activate()
|
|
{
|
|
ExecuteQueuedTasks();
|
|
Context.ExecutePendingContinuations();
|
|
}
|
|
|
|
private void ExecuteQueuedTasks()
|
|
{
|
|
while (true)
|
|
{
|
|
Task task;
|
|
|
|
lock (_tasks)
|
|
{
|
|
if (_tasks.Any())
|
|
{
|
|
task = _tasks.First.Value;
|
|
_tasks.RemoveFirst();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (task != null)
|
|
{
|
|
if (!TryExecuteTask(task))
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|