forked from enlightenment/efl
csharp: Fix free_cb calling under dotnet.
Summary: dotnet's GC seems to be more agressive, showing some issues that usually do not appear when running under Mono's. This commit uses for free_cb's the same scheme we already use for regular Eo refs, using a GC handle to keep the cleaning callback alive. Reviewers: vitor.sousa, felipealmeida, woohyun Reviewed By: vitor.sousa Subscribers: segfaultxavi, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D8593
This commit is contained in:
parent
7a55202499
commit
d775b58a63
|
@ -84,7 +84,7 @@ struct function_pointer {
|
||||||
<< scope_tab << scope_tab << scope_tab << "}\n"
|
<< scope_tab << scope_tab << scope_tab << "}\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "else\n"
|
<< scope_tab << scope_tab << scope_tab << "else\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "{\n"
|
<< scope_tab << scope_tab << scope_tab << "{\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(this._cb_free_cb, this._cb_data);\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.ThreadSafeFreeCbExec(this._cb_free_cb, this._cb_data);\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "}\n"
|
<< scope_tab << scope_tab << scope_tab << "}\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "this._cb_free_cb = null;\n"
|
<< scope_tab << scope_tab << scope_tab << "this._cb_free_cb = null;\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "this._cb_data = IntPtr.Zero;\n"
|
<< scope_tab << scope_tab << scope_tab << "this._cb_data = IntPtr.Zero;\n"
|
||||||
|
|
|
@ -628,12 +628,12 @@ struct klass
|
||||||
<< scope_tab << scope_tab << scope_tab << "else\n"
|
<< scope_tab << scope_tab << scope_tab << "else\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "{\n"
|
<< scope_tab << scope_tab << scope_tab << "{\n"
|
||||||
|
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Enter(Efl.Eo.Config.InitLock);\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Enter(Efl.All.InitLock);\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "if (Efl.Eo.Config.Initialized)\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "if (Efl.All.MainLoopInitialized)\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "{\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "{\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.efl_mono_thread_safe_native_dispose(h, gcHandlePtr);\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.efl_mono_thread_safe_native_dispose(h, gcHandlePtr);\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "}\n\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "}\n\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Exit(Efl.Eo.Config.InitLock);\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Exit(Efl.All.InitLock);\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "}\n"
|
<< scope_tab << scope_tab << scope_tab << "}\n"
|
||||||
<< scope_tab << scope_tab << "}\n"
|
<< scope_tab << scope_tab << "}\n"
|
||||||
<< scope_tab << "}\n\n"
|
<< scope_tab << "}\n\n"
|
||||||
|
|
|
@ -43,6 +43,13 @@ public static class All
|
||||||
{
|
{
|
||||||
private static bool InitializedUi = false;
|
private static bool InitializedUi = false;
|
||||||
|
|
||||||
|
public static bool MainLoopInitialized {
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly object InitLock = new object();
|
||||||
|
|
||||||
public static void Init(Efl.Csharp.Components components = Efl.Csharp.Components.Basic)
|
public static void Init(Efl.Csharp.Components components = Efl.Csharp.Components.Basic)
|
||||||
{
|
{
|
||||||
Eina.Config.Init();
|
Eina.Config.Init();
|
||||||
|
@ -56,24 +63,38 @@ public static class All
|
||||||
Efl.Ui.Config.Init();
|
Efl.Ui.Config.Init();
|
||||||
InitializedUi = true;
|
InitializedUi = true;
|
||||||
}
|
}
|
||||||
|
Monitor.Enter(InitLock);
|
||||||
|
MainLoopInitialized = true;
|
||||||
|
Monitor.Exit(InitLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Shutdowns all EFL subsystems.</summary>
|
/// <summary>Shutdowns all EFL subsystems.</summary>
|
||||||
public static void Shutdown()
|
public static void Shutdown()
|
||||||
{
|
{
|
||||||
// Try to cleanup everything before actually shutting down.
|
// Try to cleanup everything before actually shutting down.
|
||||||
|
Eina.Log.Debug("Calling GC before shutdown");
|
||||||
System.GC.Collect();
|
System.GC.Collect();
|
||||||
System.GC.WaitForPendingFinalizers();
|
System.GC.WaitForPendingFinalizers();
|
||||||
|
|
||||||
|
Monitor.Enter(InitLock);
|
||||||
|
MainLoopInitialized = false;
|
||||||
|
Monitor.Exit(InitLock);
|
||||||
|
|
||||||
if (InitializedUi)
|
if (InitializedUi)
|
||||||
{
|
{
|
||||||
|
Eina.Log.Debug("Shutting down Elementary");
|
||||||
Efl.Ui.Config.Shutdown();
|
Efl.Ui.Config.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Eina.Log.Debug("Shutting down Eldbus");
|
||||||
eldbus.Config.Shutdown();
|
eldbus.Config.Shutdown();
|
||||||
|
Eina.Log.Debug("Shutting down Evas");
|
||||||
evas_shutdown();
|
evas_shutdown();
|
||||||
|
Eina.Log.Debug("Shutting down Ecore");
|
||||||
ecore_shutdown();
|
ecore_shutdown();
|
||||||
|
Eina.Log.Debug("Shutting down Eo");
|
||||||
Efl.Eo.Config.Shutdown();
|
Efl.Eo.Config.Shutdown();
|
||||||
|
Eina.Log.Debug("Shutting down Eina");
|
||||||
Eina.Config.Shutdown();
|
Eina.Config.Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class Accessor<T> : IEnumerable<T>, IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_accessor_free, Handle);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_accessor_free, Handle);
|
||||||
}
|
}
|
||||||
Handle = IntPtr.Zero;
|
Handle = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class Array<T> : IEnumerable<T>, IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_array_free, h);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_array_free, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ public class Binbuf : IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_binbuf_free, Handle);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_binbuf_free, Handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,7 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDi
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_hash_free, h);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_hash_free, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ public class Inarray<T> : IEnumerable<T>, IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_inarray_free, h);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_inarray_free, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class Iterator<T> : IEnumerable<T>, IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_iterator_free, h);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_iterator_free, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class Strbuf : IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_strbuf_free, Handle);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_strbuf_free, Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle = IntPtr.Zero;
|
Handle = IntPtr.Zero;
|
||||||
|
|
|
@ -1411,7 +1411,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eina_value_free, this.Handle);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_value_free, this.Handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ public class Connection : IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eldbus_connection_unref, h);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eldbus_connection_unref, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,7 @@ public class Message : IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eldbus_message_unref, h);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eldbus_message_unref, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ public class Object : System.IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eldbus_object_unref, h);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eldbus_object_unref, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class Proxy : IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Efl.Eo.Globals.efl_mono_thread_safe_free_cb_exec(eldbus_proxy_unref, h);
|
Efl.Eo.Globals.ThreadSafeFreeCbExec(eldbus_proxy_unref, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class Globals
|
||||||
efl_mono_thread_safe_efl_unref(IntPtr eo);
|
efl_mono_thread_safe_efl_unref(IntPtr eo);
|
||||||
|
|
||||||
[DllImport(efl.Libs.CustomExports)] public static extern void
|
[DllImport(efl.Libs.CustomExports)] public static extern void
|
||||||
efl_mono_thread_safe_free_cb_exec(EinaFreeCb free_cb, IntPtr cb_data);
|
efl_mono_thread_safe_free_cb_exec(IntPtr free_cb, IntPtr cb_data);
|
||||||
|
|
||||||
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
||||||
efl_class_name_get(IntPtr eo);
|
efl_class_name_get(IntPtr eo);
|
||||||
|
@ -653,6 +653,7 @@ public class Globals
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Efl.FreeGCHandleCb FreeGCHandleCallbackDelegate = new Efl.FreeGCHandleCb(FreeGCHandleCallback);
|
||||||
public static void FreeGCHandleCallback(IntPtr gcHandlePtr)
|
public static void FreeGCHandleCallback(IntPtr gcHandlePtr)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -667,6 +668,7 @@ public class Globals
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Efl.RemoveEventsCb RemoveEventsCallbackDelegate = new Efl.RemoveEventsCb(RemoveEventsCallback);
|
||||||
public static void RemoveEventsCallback(IntPtr obj, IntPtr gcHandlePtr)
|
public static void RemoveEventsCallback(IntPtr obj, IntPtr gcHandlePtr)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -696,7 +698,27 @@ public class Globals
|
||||||
|
|
||||||
public static void SetNativeDisposeCallbacks()
|
public static void SetNativeDisposeCallbacks()
|
||||||
{
|
{
|
||||||
efl_mono_gchandle_callbacks_set(FreeGCHandleCallback, RemoveEventsCallback);
|
efl_mono_gchandle_callbacks_set(FreeGCHandleCallbackDelegate, RemoveEventsCallbackDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ThreadSafeFreeCbExec(EinaFreeCb cbFreeCb, IntPtr cbData)
|
||||||
|
{
|
||||||
|
EinaFreeCb cb = (IntPtr gcHandlePtr) => {
|
||||||
|
cbFreeCb(cbData);
|
||||||
|
GCHandle gcHandle = GCHandle.FromIntPtr(gcHandlePtr);
|
||||||
|
gcHandle.Free();
|
||||||
|
};
|
||||||
|
|
||||||
|
Monitor.Enter(Efl.All.InitLock);
|
||||||
|
if (Efl.All.MainLoopInitialized)
|
||||||
|
{
|
||||||
|
IntPtr cbPtr = Marshal.GetFunctionPointerForDelegate(cb);
|
||||||
|
var handle = GCHandle.Alloc(cb);
|
||||||
|
var handlePtr = GCHandle.ToIntPtr(handle);
|
||||||
|
|
||||||
|
efl_mono_thread_safe_free_cb_exec(cbPtr, handlePtr);
|
||||||
|
}
|
||||||
|
Monitor.Exit(Efl.All.InitLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Globals
|
} // Globals
|
||||||
|
@ -704,27 +726,14 @@ public class Globals
|
||||||
public static class Config
|
public static class Config
|
||||||
{
|
{
|
||||||
|
|
||||||
public static bool Initialized {
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly object InitLock = new object();
|
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
Globals.efl_object_init();
|
Globals.efl_object_init();
|
||||||
Monitor.Enter(InitLock);
|
|
||||||
Initialized = true;
|
|
||||||
Monitor.Exit(InitLock);
|
|
||||||
Globals.SetNativeDisposeCallbacks();
|
Globals.SetNativeDisposeCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Shutdown()
|
public static void Shutdown()
|
||||||
{
|
{
|
||||||
Monitor.Enter(InitLock);
|
|
||||||
Initialized = false;
|
|
||||||
Monitor.Exit(InitLock);
|
|
||||||
Globals.efl_object_shutdown();
|
Globals.efl_object_shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue