⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gsignal.c

📁 嵌入式下基于MiniGUI的Web Browser
💻 C
📖 第 1 页 / 共 5 页
字号:
/* GObject - GLib Type, Object, Parameter and Signal Library * Copyright (C) 2000-2001 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * 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. * * this code is based on the original GtkSignal implementation * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu> *//* * MT safe */#include "glibconfig.h"#include     "gsignal.h"#include    "gbsearcharray.h"#include    "gvaluecollector.h"#include	"gvaluetypes.h"#include	"gboxed.h"#include	<string.h> #include	<signal.h>/* pre allocation configurations */#define	MAX_STACK_VALUES	(16)#define HANDLER_PRE_ALLOC       (48)#define REPORT_BUG      "please report occourance circumstances to gtk-devel-list@gnome.org"#ifdef	G_ENABLE_DEBUG#define IF_DEBUG(debug_type, cond)	if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond)static volatile gpointer g_trace_instance_signals = NULL;static volatile gpointer g_trap_instance_signals = NULL;#endif	/* G_ENABLE_DEBUG *//* --- generic allocation --- *//* we special case allocations generically by replacing * these functions with more speed/memory aware variants */#ifndef	DISABLE_MEM_POOLSstatic inline gpointerg_generic_node_alloc (GTrashStack **trash_stack_p,                      guint         sizeof_node,                      guint         nodes_pre_alloc){  gpointer node = g_trash_stack_pop (trash_stack_p);    if (!node)    {      guint8 *block;            nodes_pre_alloc = MAX (nodes_pre_alloc, 1);      block = g_malloc (sizeof_node * nodes_pre_alloc);      while (--nodes_pre_alloc)        {          g_trash_stack_push (trash_stack_p, block);          block += sizeof_node;        }      node = block;    }    return node;}#define	g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)#else	/* !DISABLE_MEM_POOLS */#define	g_generic_node_alloc(t,sizeof_node,p)	 g_malloc (sizeof_node)#define	g_generic_node_free(t,node)		 g_free (node)#endif	/* !DISABLE_MEM_POOLS *//* --- typedefs --- */typedef struct _SignalNode   SignalNode;typedef struct _SignalKey    SignalKey;typedef struct _Emission     Emission;typedef struct _Handler      Handler;typedef struct _HandlerList  HandlerList;typedef struct _HandlerMatch HandlerMatch;typedef enum{  EMISSION_STOP,  EMISSION_RUN,  EMISSION_HOOK,  EMISSION_RESTART} EmissionState;/* --- prototypes --- */static inline guint		signal_id_lookup	(GQuark		  quark,							 GType		  itype);static	      void		signal_destroy_R	(SignalNode	 *signal_node);static inline HandlerList*	handler_list_ensure	(guint		  signal_id,							 gpointer	  instance);static inline HandlerList*	handler_list_lookup	(guint		  signal_id,							 gpointer	  instance);static inline Handler*		handler_new		(gboolean	  after);static	      void		handler_insert		(guint		  signal_id,							 gpointer	  instance,							 Handler	 *handler);static	      Handler*		handler_lookup		(gpointer	  instance,							 gulong		  handler_id,							 guint		 *signal_id_p);static inline HandlerMatch*	handler_match_prepend	(HandlerMatch	 *list,							 Handler	 *handler,							 guint		  signal_id);static inline HandlerMatch*	handler_match_free1_R	(HandlerMatch	 *node,							 gpointer	  instance);static	      HandlerMatch*	handlers_find		(gpointer	  instance,							 GSignalMatchType mask,							 guint		  signal_id,							 GQuark		  detail,							 GClosure	 *closure,							 gpointer	  func,							 gpointer	  data,							 gboolean	  one_and_only);static inline void		handler_ref		(Handler	 *handler);static inline void		handler_unref_R		(guint		  signal_id,							 gpointer	  instance,							 Handler	 *handler);static gint			handler_lists_cmp	(gconstpointer	  node1,							 gconstpointer	  node2);static inline void		emission_push		(Emission	**emission_list_p,							 Emission	 *emission);static inline void		emission_pop		(Emission	**emission_list_p,							 Emission	 *emission);static inline Emission*		emission_find		(Emission	 *emission_list,							 guint		  signal_id,							 GQuark		  detail,							 gpointer	  instance);static gint			class_closures_cmp	(gconstpointer	  node1,							 gconstpointer	  node2);static gint			signal_key_cmp		(gconstpointer	  node1,							 gconstpointer	  node2);static	      gboolean		signal_emit_unlocked_R	(SignalNode	 *node,							 GQuark		  detail,							 gpointer	  instance,							 GValue		 *return_value,							 const GValue	 *instance_and_params);static const gchar *            type_debug_name         (GType            type);/* --- structures --- */typedef struct{  GSignalAccumulator func;  gpointer           data;} SignalAccumulator;typedef struct{  GHook hook;  GQuark detail;} SignalHook;#define	SIGNAL_HOOK(hook)	((SignalHook*) (hook))struct _SignalNode{  /* permanent portion */  guint              signal_id;  GType              itype;  gchar             *name;  guint              destroyed : 1;    /* reinitializable portion */  guint              flags : 8;  guint              n_params : 8;  GType		    *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */  GType		     return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */  GBSearchArray     *class_closure_bsa;  SignalAccumulator *accumulator;  GSignalCMarshaller c_marshaller;  GHookList         *emission_hooks;};struct _SignalKey{  GType  itype;  GQuark quark;  guint  signal_id;};struct _Emission{  Emission             *next;  gpointer              instance;  GSignalInvocationHint ihint;  EmissionState         state;  GType			chain_type;};struct _HandlerList{  guint    signal_id;  Handler *handlers;};struct _Handler{  gulong        sequential_number;  Handler      *next;  Handler      *prev;  GQuark	detail;  guint         ref_count : 16;#define HANDLER_MAX_REF_COUNT   (1 << 16)  guint         block_count : 12;#define HANDLER_MAX_BLOCK_COUNT (1 << 12)  guint         after : 1;  GClosure     *closure;};struct _HandlerMatch{  Handler      *handler;  HandlerMatch *next;  union {    guint       signal_id;    gpointer	dummy;  } d;};typedef struct{  GType     instance_type; /* 0 for default closure */  GClosure *closure;} ClassClosure;/* --- variables --- */static GBSearchArray *g_signal_key_bsa = NULL;static GBSearchConfig g_signal_key_bconfig = G_STATIC_BCONFIG (sizeof (SignalKey),							       signal_key_cmp,							       G_BSEARCH_ARRAY_ALIGN_POWER2);static GBSearchConfig g_signal_hlbsa_bconfig = G_STATIC_BCONFIG (sizeof (HandlerList),								 handler_lists_cmp,								 G_BSEARCH_ARRAY_DEFER_SHRINK);static GBSearchConfig g_class_closure_bconfig = G_STATIC_BCONFIG (sizeof (ClassClosure),								  class_closures_cmp,								  0);static GHashTable    *g_handler_list_bsa_ht = NULL;static Emission      *g_recursive_emissions = NULL;static Emission      *g_restart_emissions = NULL;#ifndef DISABLE_MEM_POOLSstatic GTrashStack   *g_handler_ts = NULL;#endifstatic gulong         g_handler_sequential_number = 1;G_LOCK_DEFINE_STATIC (g_signal_mutex);#define	SIGNAL_LOCK()		G_LOCK (g_signal_mutex)#define	SIGNAL_UNLOCK()		G_UNLOCK (g_signal_mutex)/* --- signal nodes --- */static guint          g_n_signal_nodes = 0;static SignalNode   **g_signal_nodes = NULL;static inline SignalNode*LOOKUP_SIGNAL_NODE (register guint signal_id){  if (signal_id < g_n_signal_nodes)    return g_signal_nodes[signal_id];  else    return NULL;}/* --- functions --- */static inline guintsignal_id_lookup (GQuark quark,		  GType  itype){  GType *ifaces, type = itype;  SignalKey key;  guint n_ifaces;  key.quark = quark;  /* try looking up signals for this type and its anchestors */  do    {      SignalKey *signal_key;            key.itype = type;      signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);            if (signal_key)	return signal_key->signal_id;            type = g_type_parent (type);    }  while (type);  /* no luck, try interfaces it exports */  ifaces = g_type_interfaces (itype, &n_ifaces);  while (n_ifaces--)    {      SignalKey *signal_key;      key.itype = ifaces[n_ifaces];      signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);      if (signal_key)	{	  g_free (ifaces);	  return signal_key->signal_id;	}    }  g_free (ifaces);    return 0;}static gintclass_closures_cmp (gconstpointer node1,		    gconstpointer node2){  const ClassClosure *c1 = node1, *c2 = node2;    return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type);}static ginthandler_lists_cmp (gconstpointer node1,                   gconstpointer node2){  const HandlerList *hlist1 = node1, *hlist2 = node2;    return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);}static inline HandlerList*handler_list_ensure (guint    signal_id,		     gpointer instance){  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);  HandlerList key;    key.signal_id = signal_id;  key.handlers = NULL;  if (!hlbsa)    {      hlbsa = g_bsearch_array_new (&g_signal_hlbsa_bconfig);      hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key, FALSE);      g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);    }  else    {      GBSearchArray *o = hlbsa;      hlbsa = g_bsearch_array_insert (o, &g_signal_hlbsa_bconfig, &key, FALSE);      if (hlbsa != o)	g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);    }  return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key);}static inline HandlerList*handler_list_lookup (guint    signal_id,		     gpointer instance){  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);  HandlerList key;    key.signal_id = signal_id;    return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL;}static Handler*handler_lookup (gpointer instance,		gulong   handler_id,		guint   *signal_id_p){  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);    if (hlbsa)    {      guint i;            for (i = 0; i < hlbsa->n_nodes; i++)        {          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);          Handler *handler;                    for (handler = hlist->handlers; handler; handler = handler->next)            if (handler->sequential_number == handler_id)              {                if (signal_id_p)                  *signal_id_p = hlist->signal_id;		                return handler;              }        }    }    return NULL;}static inline HandlerMatch*handler_match_prepend (HandlerMatch *list,		       Handler      *handler,		       guint	     signal_id){  HandlerMatch *node;    /* yeah, we could use our own memchunk here, introducing yet more   * rarely used cached nodes and extra allocation overhead.   * instead, we use GList* nodes, since they are exactly the size   * we need and are already cached. g_signal_init() asserts this.   */  node = (HandlerMatch*) g_list_alloc ();  node->handler = handler;  node->next = list;  node->d.signal_id = signal_id;  handler_ref (handler);    return node;}static inline HandlerMatch*handler_match_free1_R (HandlerMatch *node,		       gpointer      instance){  HandlerMatch *next = node->next;    handler_unref_R (node->d.signal_id, instance, node->handler);  g_list_free_1 ((GList*) node);    return next;}static HandlerMatch*handlers_find (gpointer         instance,	       GSignalMatchType mask,	       guint            signal_id,	       GQuark           detail,	       GClosure        *closure,	       gpointer         func,	       gpointer         data,	       gboolean         one_and_only){  HandlerMatch *mlist = NULL;    if (mask & G_SIGNAL_MATCH_ID)    {      HandlerList *hlist = handler_list_lookup (signal_id, instance);      Handler *handler;      SignalNode *node = NULL;            if (mask & G_SIGNAL_MATCH_FUNC)	{	  node = LOOKUP_SIGNAL_NODE (signal_id);	  if (!node || !node->c_marshaller)	    return NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -