summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorCaleb Kemper <kemper.caleb@gmail.com>2023-02-11 01:30:25 -0700
committerCaleb Kemper <kemper.caleb@gmail.com>2023-02-12 14:12:09 -0700
commit103cb4bee6bdcfe793bddab6a7adf960af1f3aad (patch)
tree39617fc94f52cbcda7f2651f11811b7a6b0a88db /modules
parent929ee61170ec4d431d6d2cfeddccdec2a59a11b7 (diff)
Implement GodotSynchronizationContext.Send
Diffstat (limited to 'modules')
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs35
1 files changed, 31 insertions, 4 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
index 027eab30fc..79030c79cc 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs
@@ -1,17 +1,44 @@
using System;
using System.Collections.Concurrent;
-using System.Collections.Generic;
using System.Threading;
+using System.Threading.Tasks;
namespace Godot
{
public sealed class GodotSynchronizationContext : SynchronizationContext, IDisposable
{
- private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> _queue = new();
+ private readonly BlockingCollection<(SendOrPostCallback Callback, object State)> _queue = new();
+
+ public override void Send(SendOrPostCallback d, object state)
+ {
+ // Shortcut if we're already on this context
+ // Also necessary to avoid a deadlock, since Send is blocking
+ if (Current == this)
+ {
+ d(state);
+ return;
+ }
+
+ var source = new TaskCompletionSource();
+
+ _queue.Add((st =>
+ {
+ try
+ {
+ d(st);
+ }
+ finally
+ {
+ source.SetResult();
+ }
+ }, state));
+
+ source.Task.Wait();
+ }
public override void Post(SendOrPostCallback d, object state)
{
- _queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
+ _queue.Add((d, state));
}
/// <summary>
@@ -21,7 +48,7 @@ namespace Godot
{
while (_queue.TryTake(out var workItem))
{
- workItem.Key(workItem.Value);
+ workItem.Callback(workItem.State);
}
}