glib/libglib/src/ghook.c
branchRCL_3
changeset 57 2efc27d87e1c
parent 0 e4d67989cc36
equal deleted inserted replaced
56:acd3cd4aaceb 57:2efc27d87e1c
       
     1 /* GLIB - Library of useful routines for C programming
       
     2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
       
     3  *
       
     4  * GHook: Callback maintenance functions
       
     5  * Copyright (C) 1998 Tim Janik
       
     6  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Lesser General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
       
    16  * Lesser General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Lesser General Public
       
    19  * License along with this library; if not, write to the
       
    20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    21  * Boston, MA 02111-1307, USA.
       
    22  */
       
    23 
       
    24 /*
       
    25  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    26  * file for a list of people on the GLib Team.  See the ChangeLog
       
    27  * files for a list of changes.  These files are distributed with
       
    28  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    29  */
       
    30 
       
    31 /* 
       
    32  * MT safe
       
    33  */
       
    34 
       
    35 #include "config.h"
       
    36 
       
    37 #include "glib.h"
       
    38 #include "galias.h"
       
    39 
       
    40 
       
    41 /* --- functions --- */
       
    42 static void
       
    43 default_finalize_hook (GHookList *hook_list,
       
    44 		       GHook     *hook)
       
    45 {
       
    46   GDestroyNotify destroy = hook->destroy;
       
    47 
       
    48   if (destroy)
       
    49     {
       
    50       hook->destroy = NULL;
       
    51       destroy (hook->data);
       
    52     }
       
    53 }
       
    54 
       
    55 EXPORT_C void
       
    56 g_hook_list_init (GHookList *hook_list,
       
    57 		  guint	     hook_size)
       
    58 {
       
    59   g_return_if_fail (hook_list != NULL);
       
    60   g_return_if_fail (hook_size >= sizeof (GHook));
       
    61   
       
    62   hook_list->seq_id = 1;
       
    63   hook_list->hook_size = hook_size;
       
    64   hook_list->is_setup = TRUE;
       
    65   hook_list->hooks = NULL;
       
    66   hook_list->dummy3 = NULL;
       
    67   hook_list->finalize_hook = default_finalize_hook;
       
    68   hook_list->dummy[0] = NULL;
       
    69   hook_list->dummy[1] = NULL;
       
    70 }
       
    71 
       
    72 EXPORT_C void
       
    73 g_hook_list_clear (GHookList *hook_list)
       
    74 {
       
    75   g_return_if_fail (hook_list != NULL);
       
    76   
       
    77   if (hook_list->is_setup)
       
    78     {
       
    79       GHook *hook;
       
    80       
       
    81       hook_list->is_setup = FALSE;
       
    82       
       
    83       hook = hook_list->hooks;
       
    84       if (!hook)
       
    85 	{
       
    86 	  /* destroy hook_list->hook_memchunk */
       
    87 	}
       
    88       else
       
    89 	do
       
    90 	  {
       
    91 	    GHook *tmp;
       
    92 	    
       
    93 	    g_hook_ref (hook_list, hook);
       
    94 	    g_hook_destroy_link (hook_list, hook);
       
    95 	    tmp = hook->next;
       
    96 	    g_hook_unref (hook_list, hook);
       
    97 	    hook = tmp;
       
    98 	  }
       
    99 	while (hook);
       
   100     }
       
   101 }
       
   102 
       
   103 EXPORT_C GHook*
       
   104 g_hook_alloc (GHookList *hook_list)
       
   105 {
       
   106   GHook *hook;
       
   107   
       
   108   g_return_val_if_fail (hook_list != NULL, NULL);
       
   109   g_return_val_if_fail (hook_list->is_setup, NULL);
       
   110 
       
   111   hook = g_slice_alloc0 (hook_list->hook_size);
       
   112   hook->data = NULL;
       
   113   hook->next = NULL;
       
   114   hook->prev = NULL;
       
   115   hook->flags = G_HOOK_FLAG_ACTIVE;
       
   116   hook->ref_count = 0;
       
   117   hook->hook_id = 0;
       
   118   hook->func = NULL;
       
   119   hook->destroy = NULL;
       
   120   
       
   121   return hook;
       
   122 }
       
   123 
       
   124 EXPORT_C void
       
   125 g_hook_free (GHookList *hook_list,
       
   126 	     GHook     *hook)
       
   127 {
       
   128   g_return_if_fail (hook_list != NULL);
       
   129   g_return_if_fail (hook_list->is_setup);
       
   130   g_return_if_fail (hook != NULL);
       
   131   g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
       
   132   g_return_if_fail (!G_HOOK_IN_CALL (hook));
       
   133 
       
   134   hook_list->finalize_hook (hook_list, hook);
       
   135   g_slice_free1 (hook_list->hook_size, hook);
       
   136 }
       
   137 
       
   138 EXPORT_C void
       
   139 g_hook_destroy_link (GHookList *hook_list,
       
   140 		     GHook     *hook)
       
   141 {
       
   142   g_return_if_fail (hook_list != NULL);
       
   143   g_return_if_fail (hook != NULL);
       
   144 
       
   145   hook->flags &= ~G_HOOK_FLAG_ACTIVE;
       
   146   if (hook->hook_id)
       
   147     {
       
   148       hook->hook_id = 0;
       
   149       g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
       
   150     }
       
   151 }
       
   152 
       
   153 EXPORT_C gboolean
       
   154 g_hook_destroy (GHookList   *hook_list,
       
   155 		gulong	     hook_id)
       
   156 {
       
   157   GHook *hook;
       
   158   
       
   159   g_return_val_if_fail (hook_list != NULL, FALSE);
       
   160   g_return_val_if_fail (hook_id > 0, FALSE);
       
   161   
       
   162   hook = g_hook_get (hook_list, hook_id);
       
   163   if (hook)
       
   164     {
       
   165       g_hook_destroy_link (hook_list, hook);
       
   166       return TRUE;
       
   167     }
       
   168   
       
   169   return FALSE;
       
   170 }
       
   171 
       
   172 EXPORT_C void
       
   173 g_hook_unref (GHookList *hook_list,
       
   174 	      GHook	*hook)
       
   175 {
       
   176   g_return_if_fail (hook_list != NULL);
       
   177   g_return_if_fail (hook != NULL);
       
   178   g_return_if_fail (hook->ref_count > 0);
       
   179   
       
   180   hook->ref_count--;
       
   181   if (!hook->ref_count)
       
   182     {
       
   183       g_return_if_fail (hook->hook_id == 0);
       
   184       g_return_if_fail (!G_HOOK_IN_CALL (hook));
       
   185 
       
   186       if (hook->prev)
       
   187 	hook->prev->next = hook->next;
       
   188       else
       
   189 	hook_list->hooks = hook->next;
       
   190       if (hook->next)
       
   191 	{
       
   192 	  hook->next->prev = hook->prev;
       
   193 	  hook->next = NULL;
       
   194 	}
       
   195       hook->prev = NULL;
       
   196 
       
   197       if (!hook_list->is_setup)
       
   198 	{
       
   199 	  hook_list->is_setup = TRUE;
       
   200 	  g_hook_free (hook_list, hook);
       
   201 	  hook_list->is_setup = FALSE;
       
   202       
       
   203 	  if (!hook_list->hooks)
       
   204 	    {
       
   205 	      /* destroy hook_list->hook_memchunk */
       
   206 	    }
       
   207 	}
       
   208       else
       
   209 	g_hook_free (hook_list, hook);
       
   210     }
       
   211 }
       
   212 
       
   213 EXPORT_C GHook *
       
   214 g_hook_ref (GHookList *hook_list,
       
   215 	    GHook     *hook)
       
   216 {
       
   217   g_return_val_if_fail (hook_list != NULL, NULL);
       
   218   g_return_val_if_fail (hook != NULL, NULL);
       
   219   g_return_val_if_fail (hook->ref_count > 0, NULL);
       
   220   
       
   221   hook->ref_count++;
       
   222 
       
   223   return hook;
       
   224 }
       
   225 
       
   226 EXPORT_C void
       
   227 g_hook_prepend (GHookList *hook_list,
       
   228 		GHook	  *hook)
       
   229 {
       
   230   g_return_if_fail (hook_list != NULL);
       
   231   
       
   232   g_hook_insert_before (hook_list, hook_list->hooks, hook);
       
   233 }
       
   234 
       
   235 EXPORT_C void
       
   236 g_hook_insert_before (GHookList *hook_list,
       
   237 		      GHook	*sibling,
       
   238 		      GHook	*hook)
       
   239 {
       
   240   g_return_if_fail (hook_list != NULL);
       
   241   g_return_if_fail (hook_list->is_setup);
       
   242   g_return_if_fail (hook != NULL);
       
   243   g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
       
   244   g_return_if_fail (hook->ref_count == 0);
       
   245   
       
   246   hook->hook_id = hook_list->seq_id++;
       
   247   hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
       
   248   
       
   249   if (sibling)
       
   250     {
       
   251       if (sibling->prev)
       
   252 	{
       
   253 	  hook->prev = sibling->prev;
       
   254 	  hook->prev->next = hook;
       
   255 	  hook->next = sibling;
       
   256 	  sibling->prev = hook;
       
   257 	}
       
   258       else
       
   259 	{
       
   260 	  hook_list->hooks = hook;
       
   261 	  hook->next = sibling;
       
   262 	  sibling->prev = hook;
       
   263 	}
       
   264     }
       
   265   else
       
   266     {
       
   267       if (hook_list->hooks)
       
   268 	{
       
   269 	  sibling = hook_list->hooks;
       
   270 	  while (sibling->next)
       
   271 	    sibling = sibling->next;
       
   272 	  hook->prev = sibling;
       
   273 	  sibling->next = hook;
       
   274 	}
       
   275       else
       
   276 	hook_list->hooks = hook;
       
   277     }
       
   278 }
       
   279 
       
   280 EXPORT_C void
       
   281 g_hook_list_invoke (GHookList *hook_list,
       
   282 		    gboolean   may_recurse)
       
   283 {
       
   284   GHook *hook;
       
   285   
       
   286   g_return_if_fail (hook_list != NULL);
       
   287   g_return_if_fail (hook_list->is_setup);
       
   288 
       
   289   hook = g_hook_first_valid (hook_list, may_recurse);
       
   290   while (hook)
       
   291     {
       
   292       GHookFunc func;
       
   293       gboolean was_in_call;
       
   294       
       
   295       func = (GHookFunc) hook->func;
       
   296       
       
   297       was_in_call = G_HOOK_IN_CALL (hook);
       
   298       hook->flags |= G_HOOK_FLAG_IN_CALL;
       
   299       func (hook->data);
       
   300       if (!was_in_call)
       
   301 	hook->flags &= ~G_HOOK_FLAG_IN_CALL;
       
   302       
       
   303       hook = g_hook_next_valid (hook_list, hook, may_recurse);
       
   304     }
       
   305 }
       
   306 
       
   307 EXPORT_C void
       
   308 g_hook_list_invoke_check (GHookList *hook_list,
       
   309 			  gboolean   may_recurse)
       
   310 {
       
   311   GHook *hook;
       
   312   
       
   313   g_return_if_fail (hook_list != NULL);
       
   314   g_return_if_fail (hook_list->is_setup);
       
   315   
       
   316   hook = g_hook_first_valid (hook_list, may_recurse);
       
   317   while (hook)
       
   318     {
       
   319       GHookCheckFunc func;
       
   320       gboolean was_in_call;
       
   321       gboolean need_destroy;
       
   322       
       
   323       func = (GHookCheckFunc) hook->func;
       
   324       
       
   325       was_in_call = G_HOOK_IN_CALL (hook);
       
   326       hook->flags |= G_HOOK_FLAG_IN_CALL;
       
   327       need_destroy = !func (hook->data);
       
   328       if (!was_in_call)
       
   329 	hook->flags &= ~G_HOOK_FLAG_IN_CALL;
       
   330       if (need_destroy)
       
   331 	g_hook_destroy_link (hook_list, hook);
       
   332       
       
   333       hook = g_hook_next_valid (hook_list, hook, may_recurse);
       
   334     }
       
   335 }
       
   336 
       
   337 EXPORT_C void
       
   338 g_hook_list_marshal_check (GHookList	       *hook_list,
       
   339 			   gboolean		may_recurse,
       
   340 			   GHookCheckMarshaller marshaller,
       
   341 			   gpointer		data)
       
   342 {
       
   343   GHook *hook;
       
   344   
       
   345   g_return_if_fail (hook_list != NULL);
       
   346   g_return_if_fail (hook_list->is_setup);
       
   347   g_return_if_fail (marshaller != NULL);
       
   348   
       
   349   hook = g_hook_first_valid (hook_list, may_recurse);
       
   350   while (hook)
       
   351     {
       
   352       gboolean was_in_call;
       
   353       gboolean need_destroy;
       
   354       
       
   355       was_in_call = G_HOOK_IN_CALL (hook);
       
   356       hook->flags |= G_HOOK_FLAG_IN_CALL;
       
   357       need_destroy = !marshaller (hook, data);
       
   358       if (!was_in_call)
       
   359 	hook->flags &= ~G_HOOK_FLAG_IN_CALL;
       
   360       if (need_destroy)
       
   361 	g_hook_destroy_link (hook_list, hook);
       
   362       
       
   363       hook = g_hook_next_valid (hook_list, hook, may_recurse);
       
   364     }
       
   365 }
       
   366 
       
   367 EXPORT_C void
       
   368 g_hook_list_marshal (GHookList		     *hook_list,
       
   369 		     gboolean		      may_recurse,
       
   370 		     GHookMarshaller	      marshaller,
       
   371 		     gpointer		      data)
       
   372 {
       
   373   GHook *hook;
       
   374   
       
   375   g_return_if_fail (hook_list != NULL);
       
   376   g_return_if_fail (hook_list->is_setup);
       
   377   g_return_if_fail (marshaller != NULL);
       
   378   
       
   379   hook = g_hook_first_valid (hook_list, may_recurse);
       
   380   while (hook)
       
   381     {
       
   382       gboolean was_in_call;
       
   383       
       
   384       was_in_call = G_HOOK_IN_CALL (hook);
       
   385       hook->flags |= G_HOOK_FLAG_IN_CALL;
       
   386       marshaller (hook, data);
       
   387       if (!was_in_call)
       
   388 	hook->flags &= ~G_HOOK_FLAG_IN_CALL;
       
   389       
       
   390       hook = g_hook_next_valid (hook_list, hook, may_recurse);
       
   391     }
       
   392 }
       
   393 
       
   394 EXPORT_C GHook*
       
   395 g_hook_first_valid (GHookList *hook_list,
       
   396 		    gboolean   may_be_in_call)
       
   397 {
       
   398   g_return_val_if_fail (hook_list != NULL, NULL);
       
   399   
       
   400   if (hook_list->is_setup)
       
   401     {
       
   402       GHook *hook;
       
   403       
       
   404       hook = hook_list->hooks;
       
   405       if (hook)
       
   406 	{
       
   407 	  g_hook_ref (hook_list, hook);
       
   408 	  if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
       
   409 	    return hook;
       
   410 	  else
       
   411 	    return g_hook_next_valid (hook_list, hook, may_be_in_call);
       
   412 	}
       
   413     }
       
   414   
       
   415   return NULL;
       
   416 }
       
   417 
       
   418 EXPORT_C GHook*
       
   419 g_hook_next_valid (GHookList *hook_list,
       
   420 		   GHook     *hook,
       
   421 		   gboolean   may_be_in_call)
       
   422 {
       
   423   GHook *ohook = hook;
       
   424 
       
   425   g_return_val_if_fail (hook_list != NULL, NULL);
       
   426 
       
   427   if (!hook)
       
   428     return NULL;
       
   429   
       
   430   hook = hook->next;
       
   431   while (hook)
       
   432     {
       
   433       if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
       
   434 	{
       
   435 	  g_hook_ref (hook_list, hook);
       
   436 	  g_hook_unref (hook_list, ohook);
       
   437 	  
       
   438 	  return hook;
       
   439 	}
       
   440       hook = hook->next;
       
   441     }
       
   442   g_hook_unref (hook_list, ohook);
       
   443 
       
   444   return NULL;
       
   445 }
       
   446 
       
   447 EXPORT_C GHook*
       
   448 g_hook_get (GHookList *hook_list,
       
   449 	    gulong     hook_id)
       
   450 {
       
   451   GHook *hook;
       
   452   
       
   453   g_return_val_if_fail (hook_list != NULL, NULL);
       
   454   g_return_val_if_fail (hook_id > 0, NULL);
       
   455   
       
   456   hook = hook_list->hooks;
       
   457   while (hook)
       
   458     {
       
   459       if (hook->hook_id == hook_id)
       
   460 	return hook;
       
   461       hook = hook->next;
       
   462     }
       
   463   
       
   464   return NULL;
       
   465 }
       
   466 
       
   467 EXPORT_C GHook*
       
   468 g_hook_find (GHookList	  *hook_list,
       
   469 	     gboolean	   need_valids,
       
   470 	     GHookFindFunc func,
       
   471 	     gpointer	   data)
       
   472 {
       
   473   GHook *hook;
       
   474   
       
   475   g_return_val_if_fail (hook_list != NULL, NULL);
       
   476   g_return_val_if_fail (func != NULL, NULL);
       
   477   
       
   478   hook = hook_list->hooks;
       
   479   while (hook)
       
   480     {
       
   481       GHook *tmp;
       
   482 
       
   483       /* test only non-destroyed hooks */
       
   484       if (!hook->hook_id)
       
   485 	{
       
   486 	  hook = hook->next;
       
   487 	  continue;
       
   488 	}
       
   489       
       
   490       g_hook_ref (hook_list, hook);
       
   491       
       
   492       if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
       
   493 	{
       
   494 	  g_hook_unref (hook_list, hook);
       
   495 	  
       
   496 	  return hook;
       
   497 	}
       
   498 
       
   499       tmp = hook->next;
       
   500       g_hook_unref (hook_list, hook);
       
   501       hook = tmp;
       
   502     }
       
   503   
       
   504   return NULL;
       
   505 }
       
   506 
       
   507 EXPORT_C GHook*
       
   508 g_hook_find_data (GHookList *hook_list,
       
   509 		  gboolean   need_valids,
       
   510 		  gpointer   data)
       
   511 {
       
   512   GHook *hook;
       
   513   
       
   514   g_return_val_if_fail (hook_list != NULL, NULL);
       
   515   
       
   516   hook = hook_list->hooks;
       
   517   while (hook)
       
   518     {
       
   519       /* test only non-destroyed hooks */
       
   520       if (hook->data == data &&
       
   521 	  hook->hook_id &&
       
   522 	  (!need_valids || G_HOOK_ACTIVE (hook)))
       
   523 	return hook;
       
   524 
       
   525       hook = hook->next;
       
   526     }
       
   527   
       
   528   return NULL;
       
   529 }
       
   530 
       
   531 EXPORT_C GHook*
       
   532 g_hook_find_func (GHookList *hook_list,
       
   533 		  gboolean   need_valids,
       
   534 		  gpointer   func)
       
   535 {
       
   536   GHook *hook;
       
   537   
       
   538   g_return_val_if_fail (hook_list != NULL, NULL);
       
   539   g_return_val_if_fail (func != NULL, NULL);
       
   540   
       
   541   hook = hook_list->hooks;
       
   542   while (hook)
       
   543     {
       
   544       /* test only non-destroyed hooks */
       
   545       if (hook->func == func &&
       
   546 	  hook->hook_id &&
       
   547 	  (!need_valids || G_HOOK_ACTIVE (hook)))
       
   548 	return hook;
       
   549 
       
   550       hook = hook->next;
       
   551     }
       
   552   
       
   553   return NULL;
       
   554 }
       
   555 
       
   556 EXPORT_C GHook*
       
   557 g_hook_find_func_data (GHookList *hook_list,
       
   558 		       gboolean	  need_valids,
       
   559 		       gpointer	  func,
       
   560 		       gpointer	  data)
       
   561 {
       
   562   GHook *hook;
       
   563   
       
   564   g_return_val_if_fail (hook_list != NULL, NULL);
       
   565   g_return_val_if_fail (func != NULL, NULL);
       
   566   
       
   567   hook = hook_list->hooks;
       
   568   while (hook)
       
   569     {
       
   570       /* test only non-destroyed hooks */
       
   571       if (hook->data == data &&
       
   572 	  hook->func == func &&
       
   573 	  hook->hook_id &&
       
   574 	  (!need_valids || G_HOOK_ACTIVE (hook)))
       
   575 	return hook;
       
   576 
       
   577       hook = hook->next;
       
   578     }
       
   579   
       
   580   return NULL;
       
   581 }
       
   582 
       
   583 EXPORT_C void
       
   584 g_hook_insert_sorted (GHookList	      *hook_list,
       
   585 		      GHook	      *hook,
       
   586 		      GHookCompareFunc func)
       
   587 {
       
   588   GHook *sibling;
       
   589   
       
   590   g_return_if_fail (hook_list != NULL);
       
   591   g_return_if_fail (hook_list->is_setup);
       
   592   g_return_if_fail (hook != NULL);
       
   593   g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
       
   594   g_return_if_fail (hook->func != NULL);
       
   595   g_return_if_fail (func != NULL);
       
   596 
       
   597   /* first non-destroyed hook */
       
   598   sibling = hook_list->hooks;
       
   599   while (sibling && !sibling->hook_id)
       
   600     sibling = sibling->next;
       
   601   
       
   602   while (sibling)
       
   603     {
       
   604       GHook *tmp;
       
   605       
       
   606       g_hook_ref (hook_list, sibling);
       
   607       if (func (hook, sibling) <= 0 && sibling->hook_id)
       
   608 	{
       
   609 	  g_hook_unref (hook_list, sibling);
       
   610 	  break;
       
   611 	}
       
   612 
       
   613       /* next non-destroyed hook */
       
   614       tmp = sibling->next;
       
   615       while (tmp && !tmp->hook_id)
       
   616 	tmp = tmp->next;
       
   617 
       
   618       g_hook_unref (hook_list, sibling);
       
   619       sibling = tmp;
       
   620     }
       
   621   
       
   622   g_hook_insert_before (hook_list, sibling, hook);
       
   623 }
       
   624 
       
   625 EXPORT_C gint
       
   626 g_hook_compare_ids (GHook *new_hook,
       
   627 		    GHook *sibling)
       
   628 {
       
   629   if (new_hook->hook_id < sibling->hook_id)
       
   630     return -1;
       
   631   else if (new_hook->hook_id > sibling->hook_id)
       
   632     return 1;
       
   633   
       
   634   return 0;
       
   635 }
       
   636 
       
   637 #define __G_HOOK_C__
       
   638 #include "galiasdef.c"