mirror of
https://codeberg.org/Ikatono/TierMaker.git
synced 2025-10-28 20:45:35 -05:00
82 lines
1.7 KiB
C#
82 lines
1.7 KiB
C#
using Godot;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
/// <summary>
|
|
/// Provides defer-like behavior that's easier to work with in C#
|
|
/// </summary>
|
|
public partial class defer_manager : Node
|
|
{
|
|
// Called when the node enters the scene tree for the first time.
|
|
public override void _Ready()
|
|
{
|
|
}
|
|
private readonly ConcurrentQueue<Action> ActionQueue = new();
|
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
public override void _Process(double delta)
|
|
{
|
|
while (ActionQueue.TryDequeue(out Action a))
|
|
{
|
|
a?.Invoke();
|
|
}
|
|
}
|
|
public void DeferForget(Action action)
|
|
{
|
|
ActionQueue.Enqueue(action);
|
|
}
|
|
public async Task DeferAsync(Action action)
|
|
{
|
|
using SemaphoreSlim slim = new(0);
|
|
ActionQueue.Enqueue(() =>
|
|
{
|
|
action?.Invoke();
|
|
slim.Release();
|
|
}
|
|
);
|
|
await slim.WaitAsync();
|
|
}
|
|
public async Task<T> DeferAsync<T>(Func<T> func)
|
|
{
|
|
if (func is null)
|
|
throw new Exception("Cannot defer null function");
|
|
using SemaphoreSlim slim = new(0);
|
|
T[] box = { default };
|
|
ActionQueue.Enqueue(() =>
|
|
{
|
|
box[0] = func.Invoke();
|
|
slim.Release();
|
|
}
|
|
);
|
|
await slim.WaitAsync();
|
|
return box[0];
|
|
}
|
|
public void Defer(Action action)
|
|
{
|
|
using SemaphoreSlim slim = new(0);
|
|
ActionQueue.Enqueue(() =>
|
|
{
|
|
action?.Invoke();
|
|
slim.Release();
|
|
}
|
|
);
|
|
slim.WaitAsync();
|
|
}
|
|
public T Defer<T>(Func<T> func)
|
|
{
|
|
if (func is null)
|
|
throw new Exception("Cannot defer null function");
|
|
using SemaphoreSlim slim = new(0);
|
|
T[] box = { default };
|
|
ActionQueue.Enqueue(() =>
|
|
{
|
|
box[0] = func.Invoke();
|
|
slim.Release();
|
|
}
|
|
);
|
|
slim.WaitAsync();
|
|
return box[0];
|
|
}
|
|
}
|