Fix properties setting when constructing GLib.Objects

This is a proper fix of old FIXME.
It defers setting of managed properties during GLib.Object construction
until we have paired Managed and Unmanaged objects.
This commit is contained in:
Martin Kupec 2015-09-01 17:54:14 +02:00 committed by Harol Alfonso Reina
parent b20872aa41
commit 5a7a0f7a3c

View file

@ -36,6 +36,7 @@ namespace GLib {
bool disposed = false; bool disposed = false;
static uint idx = 1; static uint idx = 1;
static Dictionary<IntPtr, ToggleRef> Objects = new Dictionary<IntPtr, ToggleRef>(); static Dictionary<IntPtr, ToggleRef> Objects = new Dictionary<IntPtr, ToggleRef>();
static Dictionary<IntPtr, Dictionary<IntPtr, GLib.Value>> PropertiesToSet = new Dictionary<IntPtr, Dictionary<IntPtr, GLib.Value>>();
~Object () ~Object ()
{ {
@ -89,7 +90,9 @@ namespace GLib {
ToggleRef toggle_ref; ToggleRef toggle_ref;
lock (Objects) { lock (Objects) {
toggle_ref = (ToggleRef) Objects[o]; if (!Objects.TryGetValue (o, out toggle_ref)) {
return null;
}
} }
if (toggle_ref != null) { if (toggle_ref != null) {
@ -406,7 +409,9 @@ namespace GLib {
GType gtype = new GLib.GType (gtypeval); GType gtype = new GLib.GType (gtypeval);
GObjectClass threshold_class = (GObjectClass) Marshal.PtrToStructure (gtype.GetThresholdType ().GetClassPtr (), typeof (GObjectClass)); GObjectClass threshold_class = (GObjectClass) Marshal.PtrToStructure (gtype.GetThresholdType ().GetClassPtr (), typeof (GObjectClass));
IntPtr raw = threshold_class.constructor_cb (gtypeval, n_construct_properties, construct_properties); IntPtr raw = threshold_class.constructor_cb (gtypeval, n_construct_properties, construct_properties);
bool construct_needed = true; Dictionary<IntPtr, GLib.Value> deferred;
GLib.Object obj = null;
for (int i = 0; i < n_construct_properties; i++) { for (int i = 0; i < n_construct_properties; i++) {
IntPtr p = new IntPtr (construct_properties.ToInt64 () + i * 2 * IntPtr.Size); IntPtr p = new IntPtr (construct_properties.ToInt64 () + i * 2 * IntPtr.Size);
@ -417,16 +422,21 @@ namespace GLib {
Value val = (Value) Marshal.PtrToStructure (Marshal.ReadIntPtr (p, IntPtr.Size), typeof (Value)); Value val = (Value) Marshal.PtrToStructure (Marshal.ReadIntPtr (p, IntPtr.Size), typeof (Value));
if ((IntPtr) val.Val != IntPtr.Zero) { if ((IntPtr) val.Val != IntPtr.Zero) {
GCHandle gch = (GCHandle) (IntPtr) val.Val; GCHandle gch = (GCHandle) (IntPtr) val.Val;
Object o = (GLib.Object) gch.Target; obj = (GLib.Object) gch.Target;
o.Raw = raw; obj.Raw = raw;
construct_needed = false;
break; break;
} }
} }
if (construct_needed) if (obj == null)
GetObject (raw, false); obj = GetObject (raw, false);
if(PropertiesToSet.TryGetValue(raw, out deferred)) {
foreach(var item in deferred) {
SetDeferredProperty(obj, item.Value, item.Key);
}
PropertiesToSet.Remove(raw);
}
return raw; return raw;
} }
@ -511,17 +521,30 @@ namespace GLib {
static void SetPropertyCallback(IntPtr handle, uint property_id, ref GLib.Value value, IntPtr param_spec) static void SetPropertyCallback(IntPtr handle, uint property_id, ref GLib.Value value, IntPtr param_spec)
{ {
// FIXME: Here is a big quick hack to avoid race condition when trying to set up adjustment with contructor // There are multiple issues in this place.
// Because Raw is set too late // We cannot construct an object here as it can be in construction
if (param_spec != IntPtr.Zero) { // from ConstructorCallback thus managed object already created.
ParamSpec foo = new ParamSpec(param_spec); //
if (foo.Name == "gtk-sharp-managed-instance") { // We cannot use the "gtk-sharp-managed-instance" property as when
GCHandle gch = (GCHandle) (IntPtr) value.Val; // constructed by Gtk.Builder it is set to null.
Object o = (GLib.Object) gch.Target; //
o.Raw = handle; // We defer setting the properties to later time when
} // we have unmanaged and managed objects paired.
GLib.Object obj = TryGetObject(handle);
if(obj != null) {
SetDeferredProperty(obj, value, param_spec);
return;
} }
GLib.Object obj = GLib.Object.GetObject (handle, false); Dictionary<IntPtr, GLib.Value> deferred;
if(!PropertiesToSet.TryGetValue(handle, out deferred)) {
deferred = new Dictionary<IntPtr, GLib.Value>();
PropertiesToSet.Add(handle, deferred);
}
deferred[param_spec] = value;
}
static void SetDeferredProperty(GLib.Object obj, GLib.Value value, IntPtr param_spec)
{
var type = (Type)obj.LookupGType (); var type = (Type)obj.LookupGType ();
Dictionary<IntPtr, PropertyInfo> props; Dictionary<IntPtr, PropertyInfo> props;