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 << "else\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 << "this._cb_free_cb = null;\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 << "{\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "Monitor.Enter(Efl.Eo.Config.InitLock);\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "if (Efl.Eo.Config.Initialized)\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.All.MainLoopInitialized)\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 << "}\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 << "}\n"
<< scope_tab << "}\n\n"

View File

@ -43,6 +43,13 @@ public static class All
{
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)
{
Eina.Config.Init();
@ -56,24 +63,38 @@ public static class All
Efl.Ui.Config.Init();
InitializedUi = true;
}
Monitor.Enter(InitLock);
MainLoopInitialized = true;
Monitor.Exit(InitLock);
}
/// <summary>Shutdowns all EFL subsystems.</summary>
public static void Shutdown()
{
// Try to cleanup everything before actually shutting down.
Eina.Log.Debug("Calling GC before shutdown");
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
Monitor.Enter(InitLock);
MainLoopInitialized = false;
Monitor.Exit(InitLock);
if (InitializedUi)
{
Eina.Log.Debug("Shutting down Elementary");
Efl.Ui.Config.Shutdown();
}
Eina.Log.Debug("Shutting down Eldbus");
eldbus.Config.Shutdown();
Eina.Log.Debug("Shutting down Evas");
evas_shutdown();
Eina.Log.Debug("Shutting down Ecore");
ecore_shutdown();
Eina.Log.Debug("Shutting down Eo");
Efl.Eo.Config.Shutdown();
Eina.Log.Debug("Shutting down Eina");
Eina.Config.Shutdown();
}
}

View File

@ -78,7 +78,7 @@ public class Accessor<T> : IEnumerable<T>, IDisposable
}
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;
}

View File

@ -155,7 +155,7 @@ public class Array<T> : IEnumerable<T>, IDisposable
}
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
{
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
{
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
{
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
{
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
{
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;

View File

@ -1411,7 +1411,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
}
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
{
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
{
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
{
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
{
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);
[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
efl_class_name_get(IntPtr eo);
@ -653,6 +653,7 @@ public class Globals
return ret;
}
private static Efl.FreeGCHandleCb FreeGCHandleCallbackDelegate = new Efl.FreeGCHandleCb(FreeGCHandleCallback);
public static void FreeGCHandleCallback(IntPtr gcHandlePtr)
{
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)
{
try
@ -696,7 +698,27 @@ public class Globals
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
@ -704,27 +726,14 @@ public class Globals
public static class Config
{
public static bool Initialized {
get;
private set;
}
public static readonly object InitLock = new object();
public static void Init()
{
Globals.efl_object_init();
Monitor.Enter(InitLock);
Initialized = true;
Monitor.Exit(InitLock);
Globals.SetNativeDisposeCallbacks();
}
public static void Shutdown()
{
Monitor.Enter(InitLock);
Initialized = false;
Monitor.Exit(InitLock);
Globals.efl_object_shutdown();
}
}