epoc32/include/stdapis/glib-2.0/gobject/gobjectnotifyqueue.c
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
parent 0 061f57f2323e
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     1 /* GObject - GLib Type, Object, Parameter and Signal Library
     2  * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc.
     3  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
     4  *
     5  * This library is free software; you can redistribute it and/or
     6  * modify it under the terms of the GNU Lesser General Public
     7  * License as published by the Free Software Foundation; either
     8  * version 2 of the License, or (at your option) any later version.
     9  *
    10  * This library is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  * Lesser General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU Lesser General
    16  * Public License along with this library; if not, write to the
    17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
    18  * Boston, MA 02111-1307, USA.
    19  */
    20 #ifndef __G_NOTIFY_H__
    21 #define __G_NOTIFY_H__
    22 
    23 #include        <string.h> /* memset */
    24 #include        <glib-object.h>
    25 
    26 G_BEGIN_DECLS
    27 
    28 
    29 /* --- typedefs --- */
    30 #if !(EMULATOR)
    31 typedef struct _GObjectNotifyContext          GObjectNotifyContext;
    32 typedef void (*GObjectNotifyQueueDispatcher) (GObject     *object,
    33 					      guint        n_pspecs,
    34 					      GParamSpec **pspecs);
    35 #endif /* EMULATOR */
    36 
    37 typedef struct _GObjectNotifyQueue            GObjectNotifyQueue;
    38 
    39 /* --- structures --- */
    40 #if !(EMULATOR)
    41 struct _GObjectNotifyContext
    42 {
    43   GQuark                       quark_notify_queue;
    44   GObjectNotifyQueueDispatcher dispatcher;
    45   GTrashStack                 *_nqueue_trash; /* unused */
    46 };
    47 #endif /* EMULATOR */
    48 struct _GObjectNotifyQueue
    49 {
    50   GObjectNotifyContext *context;
    51   GSList               *pspecs;
    52   guint16               n_pspecs;
    53   guint16               freeze_count;
    54   /* currently, this structure abuses the GList allocation chain and thus
    55    * must be <= sizeof (GList)
    56    */
    57 };
    58 
    59 /* --- functions --- */
    60 static void
    61 g_object_notify_queue_free (gpointer data)
    62 {
    63   GObjectNotifyQueue *nqueue = data;
    64 
    65   g_slist_free (nqueue->pspecs);
    66   g_list_free_1 ((void*) nqueue);
    67 }
    68 
    69 static inline GObjectNotifyQueue*
    70 g_object_notify_queue_freeze (GObject		   *object,
    71 			      GObjectNotifyContext *context)
    72 {
    73   GObjectNotifyQueue *nqueue;
    74 
    75   nqueue = g_datalist_id_get_data (&object->qdata, context->quark_notify_queue);
    76   if (!nqueue)
    77     {
    78       nqueue = (void*) g_list_alloc ();
    79       memset (nqueue, 0, sizeof (*nqueue));
    80       nqueue->context = context;
    81       g_datalist_id_set_data_full (&object->qdata, context->quark_notify_queue,
    82 				   nqueue, g_object_notify_queue_free);
    83     }
    84 
    85   g_return_val_if_fail (nqueue->freeze_count < 65535, nqueue);
    86   nqueue->freeze_count++;
    87 
    88   return nqueue;
    89 }
    90 
    91 static inline void
    92 g_object_notify_queue_thaw (GObject            *object,
    93 			    GObjectNotifyQueue *nqueue)
    94 {
    95   GObjectNotifyContext *context = nqueue->context;
    96   GParamSpec *pspecs_mem[16], **pspecs, **free_me = NULL;
    97   GSList *slist;
    98   guint n_pspecs = 0;
    99 
   100   g_return_if_fail (nqueue->freeze_count > 0);
   101 
   102   nqueue->freeze_count--;
   103   if (nqueue->freeze_count)
   104     return;
   105   g_return_if_fail (object->ref_count > 0);
   106   pspecs = nqueue->n_pspecs > 16 ? free_me = g_new (GParamSpec*, nqueue->n_pspecs) : pspecs_mem;
   107   /* set first entry to NULL since it's checked unconditionally */
   108   pspecs[0] = NULL;
   109   for (slist = nqueue->pspecs; slist; slist = slist->next)
   110     {
   111       GParamSpec *pspec = slist->data;
   112       guint i = 0;
   113 
   114       /* dedup, make pspecs in the list unique */
   115     redo_dedup_check:
   116       if (pspecs[i] == pspec)
   117 	continue;
   118       if (++i < n_pspecs)
   119 	goto redo_dedup_check;
   120 
   121       pspecs[n_pspecs++] = pspec;
   122     }
   123   g_datalist_id_set_data (&object->qdata, context->quark_notify_queue, NULL);
   124 
   125   if (n_pspecs)
   126     context->dispatcher (object, n_pspecs, pspecs);
   127   g_free (free_me);
   128 }
   129 
   130 static inline void
   131 g_object_notify_queue_clear (GObject            *object,
   132 			     GObjectNotifyQueue *nqueue)
   133 {
   134   g_return_if_fail (nqueue->freeze_count > 0);
   135 
   136   g_slist_free (nqueue->pspecs);
   137   nqueue->pspecs = NULL;
   138   nqueue->n_pspecs = 0;
   139 }
   140 
   141 static inline void
   142 g_object_notify_queue_add (GObject            *object,
   143 			   GObjectNotifyQueue *nqueue,
   144 			   GParamSpec	      *pspec)
   145 {
   146   if (pspec->flags & G_PARAM_READABLE)
   147     {
   148       GParamSpec *redirect;
   149 
   150       g_return_if_fail (nqueue->n_pspecs < 65535);
   151 
   152       redirect = g_param_spec_get_redirect_target (pspec);
   153       if (redirect)
   154 	pspec = redirect;
   155 	    
   156       /* we do the deduping in _thaw */
   157       nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
   158       nqueue->n_pspecs++;
   159     }
   160 }
   161 
   162 static inline GObjectNotifyQueue*
   163 g_object_notify_queue_from_object (GObject              *object,
   164 				   GObjectNotifyContext *context)
   165 {
   166   return g_datalist_id_get_data (&object->qdata, context->quark_notify_queue);
   167 }
   168 G_END_DECLS
   169 
   170 #endif /* __G_NOTIFY_H__ */