X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gobject%2Fgobjectnotifyqueue.c;h=db2aa4696546c9ae53842ef19a862c3e5671fe52;hb=2a53b4d0e2c98a14aedf31e38f0ad1fb2e8fe26f;hp=8492b473706c2b321e496900779efdd27e695107;hpb=83026092eba98c2e6e0a96112555f980382a99e7;p=platform%2Fupstream%2Fglib.git diff --git a/gobject/gobjectnotifyqueue.c b/gobject/gobjectnotifyqueue.c index 8492b47..db2aa46 100644 --- a/gobject/gobjectnotifyqueue.c +++ b/gobject/gobjectnotifyqueue.c @@ -12,9 +12,13 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . + */ + +/* WARNING: + * + * This file is INSTALLED and other projects (outside of glib) + * #include its contents. */ #ifndef __G_OBJECT_NOTIFY_QUEUE_H__ @@ -50,6 +54,8 @@ struct _GObjectNotifyQueue guint16 freeze_count; }; +G_LOCK_DEFINE_STATIC(notify_lock); + /* --- functions --- */ static void g_object_notify_queue_free (gpointer data) @@ -66,6 +72,7 @@ g_object_notify_queue_freeze (GObject *object, { GObjectNotifyQueue *nqueue; + G_LOCK(notify_lock); nqueue = g_datalist_id_get_data (&object->qdata, context->quark_notify_queue); if (!nqueue) { @@ -82,6 +89,7 @@ g_object_notify_queue_freeze (GObject *object, G_OBJECT_TYPE_NAME (object), object); else nqueue->freeze_count++; + G_UNLOCK(notify_lock); return nqueue; } @@ -98,8 +106,11 @@ g_object_notify_queue_thaw (GObject *object, g_return_if_fail (nqueue->freeze_count > 0); g_return_if_fail (g_atomic_int_get(&object->ref_count) > 0); + G_LOCK(notify_lock); + /* Just make sure we never get into some nasty race condition */ if (G_UNLIKELY(nqueue->freeze_count == 0)) { + G_UNLOCK(notify_lock); g_warning ("%s: property-changed notification for %s(%p) is not frozen", G_STRFUNC, G_OBJECT_TYPE_NAME (object), object); return; @@ -107,34 +118,41 @@ g_object_notify_queue_thaw (GObject *object, nqueue->freeze_count--; if (nqueue->freeze_count) { + G_UNLOCK(notify_lock); return; } pspecs = nqueue->n_pspecs > 16 ? free_me = g_new (GParamSpec*, nqueue->n_pspecs) : pspecs_mem; - /* set first entry to NULL since it's checked unconditionally */ - pspecs[0] = NULL; + for (slist = nqueue->pspecs; slist; slist = slist->next) { - GParamSpec *pspec = slist->data; - guint i = 0; - - /* dedup, make pspecs in the list unique */ - redo_dedup_check: - if (pspecs[i] == pspec) - continue; - if (++i < n_pspecs) - goto redo_dedup_check; - - pspecs[n_pspecs++] = pspec; + pspecs[n_pspecs++] = slist->data; } g_datalist_id_set_data (&object->qdata, context->quark_notify_queue, NULL); + G_UNLOCK(notify_lock); + if (n_pspecs) context->dispatcher (object, n_pspecs, pspecs); g_free (free_me); } static inline void +g_object_notify_queue_clear (GObject *object, + GObjectNotifyQueue *nqueue) +{ + g_return_if_fail (nqueue->freeze_count > 0); + + G_LOCK(notify_lock); + + g_slist_free (nqueue->pspecs); + nqueue->pspecs = NULL; + nqueue->n_pspecs = 0; + + G_UNLOCK(notify_lock); +} + +static inline void g_object_notify_queue_add (GObject *object, GObjectNotifyQueue *nqueue, GParamSpec *pspec) @@ -143,6 +161,8 @@ g_object_notify_queue_add (GObject *object, { GParamSpec *redirect; + G_LOCK(notify_lock); + g_return_if_fail (nqueue->n_pspecs < 65535); redirect = g_param_spec_get_redirect_target (pspec); @@ -150,19 +170,28 @@ g_object_notify_queue_add (GObject *object, pspec = redirect; /* we do the deduping in _thaw */ - nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec); - nqueue->n_pspecs++; + if (g_slist_find (nqueue->pspecs, pspec) == NULL) + { + nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec); + nqueue->n_pspecs++; + } + + G_UNLOCK(notify_lock); } } +/* NB: This function is not threadsafe, do not ever use it if + * you need a threadsafe notify queue. + * Use g_object_notify_queue_freeze() to acquire the queue and + * g_object_notify_queue_thaw() after you are done instead. + */ static inline GObjectNotifyQueue* g_object_notify_queue_from_object (GObject *object, - GObjectNotifyContext *context) + GObjectNotifyContext *context) { return g_datalist_id_get_data (&object->qdata, context->quark_notify_queue); } - G_END_DECLS #endif /* __G_OBJECT_NOTIFY_QUEUE_H__ */