After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 626919 - [RFC] Let g_object_class_install_property() return the installed GParamSpec*
[RFC] Let g_object_class_install_property() return the installed GParamSpec*
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gobject
unspecified
Other Linux
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2010-08-14 10:00 UTC by Emmanuele Bassi (:ebassi)
Modified: 2010-10-08 15:06 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gobject: Add install_properties() (13.22 KB, patch)
2010-08-25 14:38 UTC, Emmanuele Bassi (:ebassi)
none Details | Review
gobject: Add install_properties() (14.37 KB, patch)
2010-08-25 22:31 UTC, Emmanuele Bassi (:ebassi)
committed Details | Review

Description Emmanuele Bassi (:ebassi) 2010-08-14 10:00:24 UTC
one of the benefits of g_object_notify_by_pspec() is to have the GParamSpecs installed as object properties available inside an array, similarly to what we do for signal ids:

  enum { PROP_0, PROP_FOO, PROP_BAR, LAST_PROPERTY };

  static GParamSpec *class_properties[LAST_PROPERTY] = { NULL, };

currently, in order to fill the ParamSpec array, you have to use a temporary GParamSpec when installing the property:

  GParamSpec *pspec;

  pspec = g_param_spec_int ("foo", "Foo", "The value of foo",
                            -1, G_MAXINT, -1,
                            G_PARAM_READWRITE);
  g_object_class_install_property (gobject_class, PROP_FOO, pspec);
  class_properties[PROP_FOO] = pspec;

but it would be more convenient to have:

  class_properties[PROP_FOO] =
    g_object_class_install_property (gobject_class, PROP_FOO, pspec);

instead.

this would not be an ABI break, as g_object_class_install_property() currently returns void.
Comment 1 Allison Karlitskaya (desrt) 2010-08-17 22:11:21 UTC
i prefer this API:

g_object_class_install_properties (GObjectClass  *class,
                                   GParamSpec   **pspecs,
                                   gint           pspecs_length);

that does this, more or less:

  g_assert (pspecs[0] == NULL);

  for (i = 1; i < pspecs_length; i++)
    g_object_install_property (class, i, pspecs[i]);


could also do it using NULL termination.



weird that we have the gap in position zero, but no biggy, i guess.  is there any reason, though, that we can't make 0 be a valid property id number?
Comment 2 Emmanuele Bassi (:ebassi) 2010-08-17 22:34:24 UTC

> i prefer this API:
> 
> g_object_class_install_properties (GObjectClass  *class,
>                                    GParamSpec   **pspecs,
>                                    gint           pspecs_length);
> 
> that does this, more or less:
> 
>   g_assert (pspecs[0] == NULL);
> 
>   for (i = 1; i < pspecs_length; i++)
>     g_object_install_property (class, i, pspecs[i]);
> 
> 
> could also do it using NULL termination.

I agree - it's more elegant, and allows us to avoid multiple argument checking (especially for classes installing a lot of properties, like ClutterActor).

> weird that we have the gap in position zero, but no biggy, i guess.  is there
> any reason, though, that we can't make 0 be a valid property id number?

I think GObject special-cases 0, but I have literally no idea why; I should probably check in the sources...(In reply to comment #1)
Comment 3 Emmanuele Bassi (:ebassi) 2010-08-25 13:43:04 UTC
pspec = 0 is special-cased for an "unattached" pspec and for pspecs installed by interfaces. I would have probably used -1 to indicate this state, but it's too late to change it now.
Comment 4 Emmanuele Bassi (:ebassi) 2010-08-25 14:38:42 UTC
Created attachment 168738 [details] [review]
gobject: Add install_properties()

Since we added g_object_notify_by_pspec(), an efficient way to install
and notify properties relies on storing the GParamSpec pointers inside
a static arrays, like we do for signal identifiers.

Instead of multiple calls to g_object_class_install_property(), we
should have a single function to take the static array of GParamSpecs
and iterate it.
Comment 5 Matthias Clasen 2010-08-25 22:05:11 UTC
Comment on attachment 168738 [details] [review]
gobject: Add install_properties()

Looks good to me.
If anything, I'd maybe call the parameter n_pspecs, to match the pspecs that it counts.
Comment 6 Emmanuele Bassi (:ebassi) 2010-08-25 22:31:55 UTC
Created attachment 168774 [details] [review]
gobject: Add install_properties()

Same as attachment 168738 [details] [review], but addressing Matthias point and adding the symbol to gobject.symbols and the API reference.
Comment 7 Allison Karlitskaya (desrt) 2010-08-26 21:12:28 UTC
sorry for the nitpick, but why did you elect to change the order of the parameters?

most of our APIs put the length field after the pointer...
Comment 8 Emmanuele Bassi (:ebassi) 2010-08-27 07:10:26 UTC
actually, in libgobject, the length of the array comes before:

gclosure.h:

typedef void (*GClosureMarshal) (GClosure       *closure,
                                 GValue         *return_value,
                               → guint           n_param_values,
                                 const GValue   *param_values,
                                 gpointer        invocation_hint,
                                 gpointer        marshal_data);

gsignal.h:

guint g_signal_newv (const gchar        *signal_name,
                     GType               itype,
                     GSignalFlags        signal_flags,
                     GClosure           *class_closure,
                     GSignalAccumulator  accumulator,
                     gpointer            accu_data,
                     GSignalCMarshaller  c_marshaller,
                     GType               return_type,
                   → guint               n_params,
                     GType              *param_types);

gtype.h:

struct _GTypeValueTable
{
  ...
  gchar* (*collect_value) (GValue       *value,
                         → guint         n_collect_values,
                           GTypeCValue  *collect_values,
                           guint         collect_flags);
  gchar   *lcopy_format;
  gchar* (*lcopy_value)   (const GValue *value,
                         → guint         n_collect_values,
                           GTypeCValue  *collect_values,
                           guint         collect_flags);
}

in gtk there are inconsistencies, sometimes in the same file like in gtkliststore.h: in insert_with_values() the length comes after, but in the constructor and the column type setter for sub-classes, it comes before.

I honestly prefer the length to be before, as it feels natural from a left-to-right reader: you're declaring the size of the following argument.

I have no problems with swapping around, though.
Comment 9 Allison Karlitskaya (desrt) 2010-08-27 10:38:28 UTC
my preference is length-after but your consistency argumentis pretty convincing and consistency (at least within libgobject)  certainly trumps my preference :)
Comment 10 Allison Karlitskaya (desrt) 2010-09-07 20:20:55 UTC
Comment on attachment 168774 [details] [review]
gobject: Add install_properties()

as per meeting
Comment 11 Emmanuele Bassi (:ebassi) 2010-09-13 11:37:52 UTC
Attachment 168774 [details] pushed as 9cd43d7 - gobject: Add install_properties()
Comment 12 Johan (not receiving bugmail) Dahlin 2010-10-04 18:06:05 UTC
I just saw this commit and I have a couple of questions which wasn't discussed.

Sorry if this is the wrong place or the wrong time to complain/nag/review this.

- If you call install_properties() for a subclass which has super class which  already implements set/get_property vtable methods it will not warn. The solution is to compare the set/get_property methods with the parent method and warn if they don't differ.
- Is the order the properties are installed ever important? If yes then a g_slist_reverse() is missing
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE should be an error, or the GParamFlags doc strings should be updated. Could warn about invalid flag combinations for overridden parameters, but that might be overkill.
- Should the GParamFlag validation be tied to install_properties(). Bw-compat might prevent it from being used elsewhere.
- The result of g_type_parent() could be cached. At the very least the parameter to g_type_parent() should be oclass_type which is fetched outside of the loop.
Comment 13 Stefan Sauer (gstreamer, gtkdoc dev) 2010-10-08 14:11:33 UTC
I also wonder if it would make sense to wrap the check for already existing psecs at the begin of install_property_internal() inside a #ifndef G_DISABLE_CHECKS

Also the current doc-blob for g_object_class_install_properties() has a typo and mentions "g_object_notify_pspec()" instead of "g_object_notify_by_pspec()".

Otherwise great stuff!
Comment 14 Emmanuele Bassi (:ebassi) 2010-10-08 15:06:31 UTC
we should probably open a new bug about improving install_propert(y|ies)...

(In reply to comment #12)
> I just saw this commit and I have a couple of questions which wasn't discussed.
> 
> Sorry if this is the wrong place or the wrong time to complain/nag/review this.
> 
> - If you call install_properties() for a subclass which has super class which 
> already implements set/get_property vtable methods it will not warn. The
> solution is to compare the set/get_property methods with the parent method and
> warn if they don't differ.

that's generally the case any way, isn't it?

actually, since the GObject class init function is going to be called during the initialization phase, I'm not sure how it's possible to have set_property/get_property to be NULL - except by explicitly setting them to NULL in the sub-class.

> - Is the order the properties are installed ever important? If yes then a
> g_slist_reverse() is missing

no, it's not important.

> - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE should be an error, or the
> GParamFlags doc strings should be updated. Could warn about invalid flag
> combinations for overridden parameters, but that might be overkill.

uh? construct-only does not imply writable: construct-only *requires* writable, and accepts readable.

> - Should the GParamFlag validation be tied to install_properties(). Bw-compat
> might prevent it from being used elsewhere.

see below.

> - The result of g_type_parent() could be cached. At the very least the
> parameter to g_type_parent() should be oclass_type which is fetched outside of
> the loop.

true.

(In reply to comment #13)
> I also wonder if it would make sense to wrap the check for already existing
> psecs at the begin of install_property_internal() inside a #ifndef
> G_DISABLE_CHECKS

we'd have to change install_property_internal() to return a boolean value, otherwise g_return_if_fail() will just go back up one level.

the reason I preferred to duplicate the checks was to make the patch the least intrusive as possible. obviously, the whole property installation check phase can be improved.

> Also the current doc-blob for g_object_class_install_properties() has a typo
> and mentions "g_object_notify_pspec()" instead of "g_object_notify_by_pspec()".

ouch. fixing it.