epoc32/include/stdapis/glib-2.0/gobject/gobjectnotifyqueue.c
branchSymbian2
changeset 2 2fe1408b6811
parent 0 061f57f2323e
equal deleted inserted replaced
1:666f914201fb 2:2fe1408b6811
     1 gobjectnotifyqueue.c
     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__ */