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:
Lauro Moura 2019-04-15 14:09:49 -03:00 committed by Vitor Sousa
parent 7a55202499
commit d775b58a63
16 changed files with 61 additions and 31 deletions

View File

@ -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"

View File

@ -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"

View File

@ -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();
} }
} }

View File

@ -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;
} }

View File

@ -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);
} }
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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;

View File

@ -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);
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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();
} }
} }