summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript_vm.cpp19
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs35
2 files changed, 42 insertions, 12 deletions
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 9b94b7a93e..7a11ea52f0 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -447,6 +447,9 @@ void (*type_init_function_table[])(Variant *) = {
#define OP_GET_BASIS get_basis
#define OP_GET_RID get_rid
+#define METHOD_CALL_ON_NULL_VALUE_ERROR(method_pointer) "Cannot call method '" + (method_pointer)->get_name() + "' on a null value."
+#define METHOD_CALL_ON_FREED_INSTANCE_ERROR(method_pointer) "Cannot call method '" + (method_pointer)->get_name() + "' on a previously freed instance."
+
Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state) {
OPCODES_TABLE;
@@ -1675,10 +1678,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool freed = false;
Object *base_obj = base->get_validated_object_with_check(freed);
if (freed) {
- err_text = "Trying to call a function on a previously freed instance.";
+ err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
OPCODE_BREAK;
} else if (!base_obj) {
- err_text = "Trying to call a function on a null value.";
+ err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
OPCODE_BREAK;
}
#else
@@ -1839,10 +1842,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool freed = false; \
Object *base_obj = base->get_validated_object_with_check(freed); \
if (freed) { \
- err_text = "Trying to call a function on a previously freed instance."; \
+ err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method); \
OPCODE_BREAK; \
} else if (!base_obj) { \
- err_text = "Trying to call a function on a null value."; \
+ err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method); \
OPCODE_BREAK; \
} \
const void **argptrs = call_args_ptr; \
@@ -1941,10 +1944,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool freed = false;
Object *base_obj = base->get_validated_object_with_check(freed);
if (freed) {
- err_text = "Trying to call a function on a previously freed instance.";
+ err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
OPCODE_BREAK;
} else if (!base_obj) {
- err_text = "Trying to call a function on a null value.";
+ err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
OPCODE_BREAK;
}
#else
@@ -2002,10 +2005,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool freed = false;
Object *base_obj = base->get_validated_object_with_check(freed);
if (freed) {
- err_text = "Trying to call a function on a previously freed instance.";
+ err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);
OPCODE_BREAK;
} else if (!base_obj) {
- err_text = "Trying to call a function on a null value.";
+ err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);
OPCODE_BREAK;
}
#else
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);
}
}