diff --git a/Dockerfile b/Dockerfile index 05323c991..8802e29ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM base/devel +FROM archlinux/archlinux:base-devel-20210627.0.27153 RUN pacman -Syy --noconfirm RUN pacman -Syu --noconfirm diff --git a/Source/generator/OpaqueGen.cs b/Source/generator/OpaqueGen.cs index c0e252620..4e6c9b1c6 100644 --- a/Source/generator/OpaqueGen.cs +++ b/Source/generator/OpaqueGen.cs @@ -106,7 +106,9 @@ public override void Generate (GenerationInfo gen_info) } } - bool finalizer_needed = false; + // GtkWidgetPath has both gtk_widget_path_unref and gtk_widget_path_free + // If this happens add only one and prefer unref over free + bool disposeUnmanagedFuncAdded = false; if (unref != null) { unref.GenerateImport (sw); @@ -118,13 +120,18 @@ public override void Generate (GenerationInfo gen_info) sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t}"); sw.WriteLine (); - + sw.WriteLine ("\t\tprotected override Action DisposeUnmanagedFunc {"); + sw.WriteLine ("\t\t\tget {"); + sw.WriteLine ("\t\t\t\treturn " + unref.CName + ";"); + sw.WriteLine ("\t\t\t}"); + sw.WriteLine ("\t\t}"); + sw.WriteLine (); + disposeUnmanagedFuncAdded = true; if (unref.IsDeprecated) { sw.WriteLine ("\t\t[Obsolete(\"" + QualifiedName + " is now refcounted automatically\")]"); sw.WriteLine ("\t\tpublic void Unref () {}"); sw.WriteLine (); } - finalizer_needed = true; } if (dispose != null) { @@ -134,43 +141,22 @@ public override void Generate (GenerationInfo gen_info) sw.WriteLine ("\t\t\t" + dispose.CName + " (raw);"); sw.WriteLine ("\t\t}"); sw.WriteLine (); + if (!disposeUnmanagedFuncAdded) { + sw.WriteLine ("\t\tprotected override Action DisposeUnmanagedFunc {"); + sw.WriteLine ("\t\t\tget {"); + sw.WriteLine ("\t\t\t\treturn " + dispose.CName + ";"); + sw.WriteLine ("\t\t\t}"); + sw.WriteLine ("\t\t}"); + sw.WriteLine (); + } if (dispose.IsDeprecated) { sw.WriteLine ("\t\t[Obsolete(\"" + QualifiedName + " is now freed automatically\")]"); sw.WriteLine ("\t\tpublic void " + dispose.Name + " () {}"); sw.WriteLine (); } - finalizer_needed = true; } - if (finalizer_needed) { - sw.WriteLine ("\t\tclass FinalizerInfo {"); - sw.WriteLine ("\t\t\tIntPtr handle;"); - sw.WriteLine (); - sw.WriteLine ("\t\t\tpublic FinalizerInfo (IntPtr handle)"); - sw.WriteLine ("\t\t\t{"); - sw.WriteLine ("\t\t\t\tthis.handle = handle;"); - sw.WriteLine ("\t\t\t}"); - sw.WriteLine (); - sw.WriteLine ("\t\t\tpublic bool Handler ()"); - sw.WriteLine ("\t\t\t{"); - if (dispose != null) - sw.WriteLine ("\t\t\t\t{0} (handle);", dispose.CName); - else if (unref != null) - sw.WriteLine ("\t\t\t\t{0} (handle);", unref.CName); - sw.WriteLine ("\t\t\t\treturn false;"); - sw.WriteLine ("\t\t\t}"); - sw.WriteLine ("\t\t}"); - sw.WriteLine (); - sw.WriteLine ("\t\t~{0} ()", Name); - sw.WriteLine ("\t\t{"); - sw.WriteLine ("\t\t\tif (!Owned)"); - sw.WriteLine ("\t\t\t\treturn;"); - sw.WriteLine ("\t\t\tFinalizerInfo info = new FinalizerInfo (Handle);"); - sw.WriteLine ("\t\t\tGLib.Timeout.Add (50, new GLib.TimeoutHandler (info.Handler));"); - sw.WriteLine ("\t\t}"); - sw.WriteLine (); - } #if false Method copy = Methods ["Copy"] as Method; diff --git a/Source/glib/Opaque.cs b/Source/glib/Opaque.cs index 955285f6a..2955ae8b0 100644 --- a/Source/glib/Opaque.cs +++ b/Source/glib/Opaque.cs @@ -81,14 +81,78 @@ protected IntPtr Raw { Ref (_obj); } } - } + } + + #region IDisposable implementation + class FinalizerInfo + { + IntPtr handle; + Action unrefFunc; + + public FinalizerInfo (Action unrefFunc, IntPtr handle) + { + this.handle = handle; + this.unrefFunc = unrefFunc; + } + + public bool Handler () + { + unrefFunc (handle); + return false; + } + } - public virtual void Dispose () + ~Opaque () + { + Dispose (false); + } + + public void Dispose () { Raw = IntPtr.Zero; + Dispose (true); GC.SuppressFinalize (this); } + protected void Dispose (bool disposing) + { + if (Disposed) + return; + Disposed = true; + if (disposing) { + DisposeManagedResources (); + } + DisposeUnmanagedResources (); + } + + /// + /// Disposes the managed resources. + /// This method is intended to be overriden. + /// + protected virtual void DisposeManagedResources () + { + } + + /// + /// Disposes the unmanaged resources. + /// This method is intended to be overriden. + /// + protected virtual void DisposeUnmanagedResources () + { + if (!Owned || DisposeUnmanagedFunc == null) + return; + FinalizerInfo info = new FinalizerInfo (DisposeUnmanagedFunc, Handle); + Timeout.Add (50, new TimeoutHandler (info.Handler)); + } + + protected internal bool Disposed { get; private set; } = false; + + protected virtual Action DisposeUnmanagedFunc { get; } + + #endregion + + + // These take an IntPtr arg so we don't get conflicts if we need // to have an "[Obsolete] public void Ref ()"