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 617446 - Allow custom code to be executed when dispatching a NotifyQueue
Allow custom code to be executed when dispatching a NotifyQueue
Status: RESOLVED OBSOLETE
Product: glib
Classification: Platform
Component: gobject
unspecified
Other Linux
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks: gcontroller
 
 
Reported: 2010-05-02 14:40 UTC by Emmanuele Bassi (:ebassi)
Modified: 2018-05-24 12:15 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
object: Add ::thaw-notify signal (2.15 KB, patch)
2010-06-02 13:56 UTC, Emmanuele Bassi (:ebassi)
none Details | Review

Description Emmanuele Bassi (:ebassi) 2010-05-02 14:40:06 UTC
currently, the ::notify signal is emitted per-property. for complex objects changing different properties at the same time it's possible to compress the notification queue using the freeze...notify+...thaw mechanism. this, however, keeps the ::notify signal emission per-property, to maintain invariants and API guarantees.

it is not possible though, from within the ::notify signal emission, to know how many properties are going to be notified, or how many are left.

for instance, given a GObjectController class following the design at:

  http://live.gnome.org/EmmanueleBassi/GController

which would allow emitting a ::changed signal with a reference to all the properties that have been changed between a freeze_notify() and a thaw_notify(), there is no way to actually implement bulk notification without sub-classing GObject and change the dispatch_properties_changed virtual function inside the GObjectClass vtable. this obviously lacks generality, as it would only work with a specific sub-type of GObject.

rationale: this is a slightly more complex way of dealing with the notification of changes on object properties by it allows:

  • better performance in case of bulk changes (a single notification
    function instead of multiple ones);
  • a reusable MVC design for creating UI elements binding to objects;
  • a structured property change notification that is detached from
    the GObject class and allows further changes without requiring
    changes to the GObject class itself.

unfortunately, I have no well defined proposal on how to make this work within the GObject class implementation; creating a ::dispatch-properties-changed signal would overlap the ::notify signal and would confuse the overall GObject design.

adding a callback mechanism similar to the weak/toggle references would in theory work:

  void g_object_add_property_dispatch (GObject *gobject,
                                       GPropertyDispatchCallback callback,
                                       gpointer user_data,
                                       GDestroyNotify notify);

though I feel it's a bit on the clunky side of the API.

another possible angle of attack would be the ability to retrieve the GObjectNotifyContext from an object and add a callback for the dispatcher to allow third party code to run before/after the GObject dispatcher.

finally, a fourth option would be to allow querying a GObject during the ::notify signal emission how many properties are left, so that third party code can connect to the ::notify signal and do something like:

  static void
  on_notify (GObject *gobject,
             GParamSpec *pspec,
             GController *controller)
  {
    static GControllerReference *ref;
    static guint counter = 0;

    guint n_props = g_object_get_notify_count (gobject);

    /* first emission */
    if (ref == NULL)
      ref = g_controller_create_reference (controller, ...);

    g_controller_reference_add_index (ref, counter, pspec->name);

    /* last property: emit the ::changed signal */
    if (n_props == 0)
      {
        g_controller_emit_changed (controller, ref);
        g_object_unref (ref);

        /* reset for the next notification emission */
        ref = NULL
        counter = 0;
      }
    else
      counter += 1;
  }

which is slightly more clunky but still feasible.
Comment 1 Ray Strode [halfline] 2010-05-12 02:51:48 UTC
What about a 'thaw-notify' signal that gets emitted at the top of g_object_notify_queue_thaw or 'notify-thawed' at the bottom of that function?

It would be very similar to your 'dispatch-properties-changed' idea but be specific to freezing/thawing batched updates instead of getting emitted for every change.  This way it would sort of fit along-side 'notify' in the API instead of rendering it redundant.
Comment 2 Emmanuele Bassi (:ebassi) 2010-05-12 09:37:37 UTC
I like the idea of a ::thaw-notify signal. a lot, actually.
Comment 3 Emmanuele Bassi (:ebassi) 2010-06-02 13:56:18 UTC
Created attachment 162539 [details] [review]
object: Add ::thaw-notify signal

The ::thaw-notify signal is emitted then the NotifyQueue for an object
is fully thawed, and the property changes are dispatched. The signal
allows arbitrary code to get a bulk notification in case multiple
properties changed in the same queue, to avoid multiple invocations of
the GObject::notify signal.
Comment 4 Emmanuele Bassi (:ebassi) 2013-08-19 11:43:48 UTC
given the high overhead of a signal, and given the critical path of property notification, I was thinking of having a GDispatchFunc callback registered on a per-object basis.

aside from GController, this could would be useful for animation frameworks based on properties; it would allow compressing all animation changes done during the frame advancement to cause a single state update, even for interdependent properties - e.g. change the transformation matrix once, after the decomposed transformations (rotate, scale, translate) have been updated; or update the boundaries of a scene graph element once, after the positional and dimensional properties have been changed.

the API would look like:

  g_object_add_dispatch_notify (GObject *, GDispatchFunc, gpointer, GDestroyNotify)

and GDispatchFunc would have the following signature:

  void (* GDispatchFunc) (GObject *, GParamSpec **pspec, guint n_pspecs)

something cute would be dispatching the property notification in the same main context as the g_object_add_dispatch_notify() func was called.
Comment 5 GNOME Infrastructure Team 2018-05-24 12:15:56 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/glib/issues/290.