virtualx-engine/modules/mono/glue/Managed/Files/GodotTaskScheduler.cs

92 lines
2.2 KiB
C#
Raw Normal View History

2017-10-02 23:24:00 +02:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Godot
{
2018-09-07 03:08:16 +02:00
public class GodotTaskScheduler : TaskScheduler
{
internal GodotSynchronizationContext Context { get; }
2018-09-07 03:08:16 +02:00
private readonly LinkedList<Task> _tasks = new LinkedList<Task>();
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
public GodotTaskScheduler()
{
Context = new GodotSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(Context);
}
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
protected sealed override void QueueTask(Task task)
{
lock (_tasks)
{
_tasks.AddLast(task);
}
}
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
if (SynchronizationContext.Current != Context)
return false;
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
if (taskWasPreviouslyQueued)
TryDequeue(task);
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
return TryExecuteTask(task);
}
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
protected sealed override bool TryDequeue(Task task)
{
lock (_tasks)
{
return _tasks.Remove(task);
}
}
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
protected sealed override IEnumerable<Task> GetScheduledTasks()
{
lock (_tasks)
{
foreach (Task task in _tasks)
yield return task;
2018-09-07 03:08:16 +02:00
}
}
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
public void Activate()
{
ExecuteQueuedTasks();
Context.ExecutePendingContinuations();
}
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
private void ExecuteQueuedTasks()
{
while (true)
{
Task task;
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
lock (_tasks)
{
if (_tasks.Any())
{
task = _tasks.First.Value;
_tasks.RemoveFirst();
}
else
{
break;
}
}
2017-10-02 23:24:00 +02:00
2018-09-07 03:08:16 +02:00
if (task != null)
{
if (!TryExecuteTask(task))
{
throw new InvalidOperationException();
}
}
}
}
}
2017-10-02 23:24:00 +02:00
}