ok, there have been several severe bugs in the signal handler referencing

Tue Feb 10 07:12:07 1998  Tim Janik  <timj@gimp.org>

        * gtk/gtksignal.h:
        * gtk/gtksignal.c:
        ok, there have been several severe bugs in the signal handler
        referencing and ->next connection stuff. these bugs caused
        invokations of handlers that are disconnected and - worse -
        destroyed already. invokation of *destroyd* handlers mean:
        anything can be executed , because the handler structure can just
        as well be realocated.
        at the cost of an extra ->prev field per handler we should have a
        reasonable stable system now, because of the various places that
        can cause a handler to be disconnected (*any* handler invokation can
        cause *any* or *all* handlers to be disconnected, there is no way
        around a doubly linked list, actually handler disconnection has never
        worked correctly because of this.
        handlers are connected together via a *doubly* linked list now, and it
        is *not* valid to remove a handler out of this list untill all its
        references have been droped, i.e. handler->ref_count==0.
        to prevent emissions of disconnected but still referenced handlers,
        disconnected handlers are simply marked as blocked and get an id of 0
        which is an invalid signal handler id.
        the handler->id has been changed to have 28 significant bits (using
        alignment gaps), since 65536 (old range: guint16) signal connections
        (as a total) can easily be reached by complex applications.
        this whole handler thingy is at least as tedious as writing doubly
        linked list implementations ;)
This commit is contained in:
Tim Janik
1998-02-10 06:53:08 +00:00
committed by Tim Janik
parent f98686da85
commit 6898536a02
10 changed files with 326 additions and 136 deletions

View File

@ -1,3 +1,31 @@
Tue Feb 10 07:12:07 1998 Tim Janik <timj@gimp.org>
* gtk/gtksignal.h:
* gtk/gtksignal.c:
ok, there have been several severe bugs in the signal handler
referencing and ->next connection stuff. these bugs caused
invokations of handlers that are disconnected and - worse -
destroyed already. invokation of *destroyd* handlers mean:
anything can be executed , because the handler structure can just
as well be realocated.
at the cost of an extra ->prev field per handler we should have a
reasonable stable system now, because of the various places that
can cause a handler to be disconnected (*any* handler invokation can
cause *any* or *all* handlers to be disconnected, there is no way
around a doubly linked list, actually handler disconnection has never
worked correctly because of this.
handlers are connected together via a *doubly* linked list now, and it
is *not* valid to remove a handler out of this list untill all its
references have been droped, i.e. handler->ref_count==0.
to prevent emissions of disconnected but still referenced handlers,
disconnected handlers are simply marked as blocked and get an id of 0
which is an invalid signal handler id.
the handler->id has been changed to have 28 significant bits (using
alignment gaps), since 65536 (old range: guint16) signal connections
(as a total) can easily be reached by complex applications.
this whole handler thingy is at least as tedious as writing doubly
linked list implementations ;)
Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu> Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtkwidget.c (gtk_widget_unparent): Check for * gtk/gtkwidget.c (gtk_widget_unparent): Check for

View File

@ -1,3 +1,31 @@
Tue Feb 10 07:12:07 1998 Tim Janik <timj@gimp.org>
* gtk/gtksignal.h:
* gtk/gtksignal.c:
ok, there have been several severe bugs in the signal handler
referencing and ->next connection stuff. these bugs caused
invokations of handlers that are disconnected and - worse -
destroyed already. invokation of *destroyd* handlers mean:
anything can be executed , because the handler structure can just
as well be realocated.
at the cost of an extra ->prev field per handler we should have a
reasonable stable system now, because of the various places that
can cause a handler to be disconnected (*any* handler invokation can
cause *any* or *all* handlers to be disconnected, there is no way
around a doubly linked list, actually handler disconnection has never
worked correctly because of this.
handlers are connected together via a *doubly* linked list now, and it
is *not* valid to remove a handler out of this list untill all its
references have been droped, i.e. handler->ref_count==0.
to prevent emissions of disconnected but still referenced handlers,
disconnected handlers are simply marked as blocked and get an id of 0
which is an invalid signal handler id.
the handler->id has been changed to have 28 significant bits (using
alignment gaps), since 65536 (old range: guint16) signal connections
(as a total) can easily be reached by complex applications.
this whole handler thingy is at least as tedious as writing doubly
linked list implementations ;)
Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu> Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtkwidget.c (gtk_widget_unparent): Check for * gtk/gtkwidget.c (gtk_widget_unparent): Check for

View File

@ -1,3 +1,31 @@
Tue Feb 10 07:12:07 1998 Tim Janik <timj@gimp.org>
* gtk/gtksignal.h:
* gtk/gtksignal.c:
ok, there have been several severe bugs in the signal handler
referencing and ->next connection stuff. these bugs caused
invokations of handlers that are disconnected and - worse -
destroyed already. invokation of *destroyd* handlers mean:
anything can be executed , because the handler structure can just
as well be realocated.
at the cost of an extra ->prev field per handler we should have a
reasonable stable system now, because of the various places that
can cause a handler to be disconnected (*any* handler invokation can
cause *any* or *all* handlers to be disconnected, there is no way
around a doubly linked list, actually handler disconnection has never
worked correctly because of this.
handlers are connected together via a *doubly* linked list now, and it
is *not* valid to remove a handler out of this list untill all its
references have been droped, i.e. handler->ref_count==0.
to prevent emissions of disconnected but still referenced handlers,
disconnected handlers are simply marked as blocked and get an id of 0
which is an invalid signal handler id.
the handler->id has been changed to have 28 significant bits (using
alignment gaps), since 65536 (old range: guint16) signal connections
(as a total) can easily be reached by complex applications.
this whole handler thingy is at least as tedious as writing doubly
linked list implementations ;)
Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu> Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtkwidget.c (gtk_widget_unparent): Check for * gtk/gtkwidget.c (gtk_widget_unparent): Check for

View File

@ -1,3 +1,31 @@
Tue Feb 10 07:12:07 1998 Tim Janik <timj@gimp.org>
* gtk/gtksignal.h:
* gtk/gtksignal.c:
ok, there have been several severe bugs in the signal handler
referencing and ->next connection stuff. these bugs caused
invokations of handlers that are disconnected and - worse -
destroyed already. invokation of *destroyd* handlers mean:
anything can be executed , because the handler structure can just
as well be realocated.
at the cost of an extra ->prev field per handler we should have a
reasonable stable system now, because of the various places that
can cause a handler to be disconnected (*any* handler invokation can
cause *any* or *all* handlers to be disconnected, there is no way
around a doubly linked list, actually handler disconnection has never
worked correctly because of this.
handlers are connected together via a *doubly* linked list now, and it
is *not* valid to remove a handler out of this list untill all its
references have been droped, i.e. handler->ref_count==0.
to prevent emissions of disconnected but still referenced handlers,
disconnected handlers are simply marked as blocked and get an id of 0
which is an invalid signal handler id.
the handler->id has been changed to have 28 significant bits (using
alignment gaps), since 65536 (old range: guint16) signal connections
(as a total) can easily be reached by complex applications.
this whole handler thingy is at least as tedious as writing doubly
linked list implementations ;)
Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu> Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtkwidget.c (gtk_widget_unparent): Check for * gtk/gtkwidget.c (gtk_widget_unparent): Check for

View File

@ -1,3 +1,31 @@
Tue Feb 10 07:12:07 1998 Tim Janik <timj@gimp.org>
* gtk/gtksignal.h:
* gtk/gtksignal.c:
ok, there have been several severe bugs in the signal handler
referencing and ->next connection stuff. these bugs caused
invokations of handlers that are disconnected and - worse -
destroyed already. invokation of *destroyd* handlers mean:
anything can be executed , because the handler structure can just
as well be realocated.
at the cost of an extra ->prev field per handler we should have a
reasonable stable system now, because of the various places that
can cause a handler to be disconnected (*any* handler invokation can
cause *any* or *all* handlers to be disconnected, there is no way
around a doubly linked list, actually handler disconnection has never
worked correctly because of this.
handlers are connected together via a *doubly* linked list now, and it
is *not* valid to remove a handler out of this list untill all its
references have been droped, i.e. handler->ref_count==0.
to prevent emissions of disconnected but still referenced handlers,
disconnected handlers are simply marked as blocked and get an id of 0
which is an invalid signal handler id.
the handler->id has been changed to have 28 significant bits (using
alignment gaps), since 65536 (old range: guint16) signal connections
(as a total) can easily be reached by complex applications.
this whole handler thingy is at least as tedious as writing doubly
linked list implementations ;)
Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu> Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtkwidget.c (gtk_widget_unparent): Check for * gtk/gtkwidget.c (gtk_widget_unparent): Check for

View File

@ -1,3 +1,31 @@
Tue Feb 10 07:12:07 1998 Tim Janik <timj@gimp.org>
* gtk/gtksignal.h:
* gtk/gtksignal.c:
ok, there have been several severe bugs in the signal handler
referencing and ->next connection stuff. these bugs caused
invokations of handlers that are disconnected and - worse -
destroyed already. invokation of *destroyd* handlers mean:
anything can be executed , because the handler structure can just
as well be realocated.
at the cost of an extra ->prev field per handler we should have a
reasonable stable system now, because of the various places that
can cause a handler to be disconnected (*any* handler invokation can
cause *any* or *all* handlers to be disconnected, there is no way
around a doubly linked list, actually handler disconnection has never
worked correctly because of this.
handlers are connected together via a *doubly* linked list now, and it
is *not* valid to remove a handler out of this list untill all its
references have been droped, i.e. handler->ref_count==0.
to prevent emissions of disconnected but still referenced handlers,
disconnected handlers are simply marked as blocked and get an id of 0
which is an invalid signal handler id.
the handler->id has been changed to have 28 significant bits (using
alignment gaps), since 65536 (old range: guint16) signal connections
(as a total) can easily be reached by complex applications.
this whole handler thingy is at least as tedious as writing doubly
linked list implementations ;)
Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu> Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtkwidget.c (gtk_widget_unparent): Check for * gtk/gtkwidget.c (gtk_widget_unparent): Check for

View File

@ -1,3 +1,31 @@
Tue Feb 10 07:12:07 1998 Tim Janik <timj@gimp.org>
* gtk/gtksignal.h:
* gtk/gtksignal.c:
ok, there have been several severe bugs in the signal handler
referencing and ->next connection stuff. these bugs caused
invokations of handlers that are disconnected and - worse -
destroyed already. invokation of *destroyd* handlers mean:
anything can be executed , because the handler structure can just
as well be realocated.
at the cost of an extra ->prev field per handler we should have a
reasonable stable system now, because of the various places that
can cause a handler to be disconnected (*any* handler invokation can
cause *any* or *all* handlers to be disconnected, there is no way
around a doubly linked list, actually handler disconnection has never
worked correctly because of this.
handlers are connected together via a *doubly* linked list now, and it
is *not* valid to remove a handler out of this list untill all its
references have been droped, i.e. handler->ref_count==0.
to prevent emissions of disconnected but still referenced handlers,
disconnected handlers are simply marked as blocked and get an id of 0
which is an invalid signal handler id.
the handler->id has been changed to have 28 significant bits (using
alignment gaps), since 65536 (old range: guint16) signal connections
(as a total) can easily be reached by complex applications.
this whole handler thingy is at least as tedious as writing doubly
linked list implementations ;)
Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu> Mon Feb 9 23:08:16 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtkwidget.c (gtk_widget_unparent): Check for * gtk/gtkwidget.c (gtk_widget_unparent): Check for

View File

@ -100,7 +100,7 @@ static void gtk_message (gchar *str);
static void gtk_print (gchar *str); static void gtk_print (gchar *str);
static gint done; static gboolean iteration_done = FALSE;
static guint main_level = 0; static guint main_level = 0;
static gint initialized = FALSE; static gint initialized = FALSE;
static GdkEvent *next_event = NULL; static GdkEvent *next_event = NULL;
@ -214,10 +214,10 @@ gtk_main ()
g_list_free (functions); g_list_free (functions);
old_done = done; old_done = iteration_done;
while (!gtk_main_iteration ()) while (!gtk_main_iteration ())
; ;
done = old_done; iteration_done = old_done;
main_level--; main_level--;
} }
@ -231,7 +231,7 @@ gtk_main_level (void)
void void
gtk_main_quit () gtk_main_quit ()
{ {
done = TRUE; iteration_done = TRUE;
} }
gint gint
@ -254,7 +254,7 @@ gtk_main_iteration_do (gboolean blocking)
GdkEvent *event = NULL; GdkEvent *event = NULL;
GList *tmp_list; GList *tmp_list;
done = FALSE; iteration_done = FALSE;
/* If this is a recursive call, and there are pending timeouts or /* If this is a recursive call, and there are pending timeouts or
* idles, finish them, then return immediately to avoid blocking * idles, finish them, then return immediately to avoid blocking
@ -263,12 +263,12 @@ gtk_main_iteration_do (gboolean blocking)
if (current_timeouts) if (current_timeouts)
{ {
gtk_handle_current_timeouts( gdk_time_get()); gtk_handle_current_timeouts( gdk_time_get());
return done; return iteration_done;
} }
if (current_idles) if (current_idles)
{ {
gtk_handle_current_idles(); gtk_handle_current_idles();
return done; return iteration_done;
} }
/* If there is a valid event in 'next_event' then move it to 'event' /* If there is a valid event in 'next_event' then move it to 'event'
@ -479,7 +479,7 @@ event_handling_done:
*/ */
gtk_handle_timeouts (); gtk_handle_timeouts ();
return done; return iteration_done;
} }
gint gint

View File

@ -119,8 +119,8 @@ static void gtk_params_get (GtkArg *params,
static gint initialize = TRUE; static gint initialize = TRUE;
static GHashTable *signal_hash_table = NULL; static GHashTable *signal_hash_table = NULL;
static GHashTable *signal_info_hash_table = NULL; static GHashTable *signal_info_hash_table = NULL;
static gint next_signal = 1; static guint next_signal = 1;
static gint next_handler_id = 1; static guint next_handler_id = 1;
static const gchar *handler_key = "gtk-signal-handlers"; static const gchar *handler_key = "gtk-signal-handlers";
@ -600,62 +600,56 @@ gtk_signal_connect_object_while_alive (GtkObject *object,
void void
gtk_signal_disconnect (GtkObject *object, gtk_signal_disconnect (GtkObject *object,
gint anid) gint an_id)
{ {
GtkHandler *tmp; GtkHandler *handler;
GtkHandler *prev;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
g_return_if_fail (an_id > 0);
if (initialize) handler = gtk_object_get_data (object, handler_key);
gtk_signal_init ();
prev = NULL; while (handler)
tmp = gtk_object_get_data (object, handler_key);
while (tmp)
{ {
if (tmp->id == anid) if (handler->id == an_id)
{ {
if (prev) handler->id = 0;
prev->next = tmp->next; handler->blocked = TRUE;
else gtk_signal_handler_unref (handler, object);
gtk_signal_handler_unref (tmp, object);
return; return;
} }
handler = handler->next;
prev = tmp;
tmp = tmp->next;
} }
g_warning ("gtk_signal_disconnect(): could not find handler (%d)", anid); g_warning ("gtk_signal_disconnect(): could not find handler (%d)", an_id);
} }
void void
gtk_signal_disconnect_by_data (GtkObject *object, gtk_signal_disconnect_by_data (GtkObject *object,
gpointer data) gpointer data)
{ {
GtkHandler *tmp; GtkHandler *handler;
GtkHandler *next;
gint found_one; gint found_one;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
if (initialize)
gtk_signal_init ();
tmp = gtk_object_get_data (object, handler_key);
found_one = FALSE; found_one = FALSE;
handler = gtk_object_get_data (object, handler_key);
while (tmp)
while (handler)
{ {
next = tmp->next; GtkHandler *handler_next;
if (tmp->func_data == data)
handler_next = handler->next;
if (handler->func_data == data &&
handler->id > 0)
{ {
found_one = TRUE; found_one = TRUE;
gtk_signal_handler_unref (tmp, object); handler->id = 0;
handler->blocked = TRUE;
gtk_signal_handler_unref (handler, object);
} }
tmp = next; handler = handler_next;
} }
if (!found_one) if (!found_one)
@ -664,20 +658,18 @@ gtk_signal_disconnect_by_data (GtkObject *object,
void void
gtk_signal_handler_block (GtkObject *object, gtk_signal_handler_block (GtkObject *object,
gint anid) gint an_id)
{ {
GtkHandler *tmp; GtkHandler *tmp;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
g_return_if_fail (an_id > 0);
if (initialize)
gtk_signal_init ();
tmp = gtk_object_get_data (object, handler_key); tmp = gtk_object_get_data (object, handler_key);
while (tmp) while (tmp)
{ {
if (tmp->id == anid) if (tmp->id == an_id)
{ {
tmp->blocked = TRUE; tmp->blocked = TRUE;
return; return;
@ -686,14 +678,14 @@ gtk_signal_handler_block (GtkObject *object,
tmp = tmp->next; tmp = tmp->next;
} }
g_warning ("gtk_signal_handler_block(): could not find handler (%d)", anid); g_warning ("gtk_signal_handler_block(): could not find handler (%d)", an_id);
} }
void void
gtk_signal_handler_block_by_data (GtkObject *object, gtk_signal_handler_block_by_data (GtkObject *object,
gpointer data) gpointer data)
{ {
GtkHandler *tmp; GtkHandler *handler;
gint found_one; gint found_one;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
@ -702,17 +694,18 @@ gtk_signal_handler_block_by_data (GtkObject *object,
gtk_signal_init (); gtk_signal_init ();
found_one = FALSE; found_one = FALSE;
tmp = gtk_object_get_data (object, handler_key); handler = gtk_object_get_data (object, handler_key);
while (tmp) while (handler)
{ {
if (tmp->func_data == data) if (handler->func_data == data &&
handler->id > 0)
{ {
tmp->blocked = TRUE;
found_one = TRUE; found_one = TRUE;
handler->blocked = TRUE;
} }
tmp = tmp->next; handler = handler->next;
} }
if (!found_one) if (!found_one)
@ -721,36 +714,37 @@ gtk_signal_handler_block_by_data (GtkObject *object,
void void
gtk_signal_handler_unblock (GtkObject *object, gtk_signal_handler_unblock (GtkObject *object,
gint anid) gint an_id)
{ {
GtkHandler *tmp; GtkHandler *handler;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
g_return_if_fail (an_id > 0);
if (initialize) if (initialize)
gtk_signal_init (); gtk_signal_init ();
tmp = gtk_object_get_data (object, handler_key); handler = gtk_object_get_data (object, handler_key);
while (tmp) while (handler)
{ {
if (tmp->id == anid) if (handler->id == an_id)
{ {
tmp->blocked = FALSE; handler->blocked = FALSE;
return; return;
} }
tmp = tmp->next; handler = handler->next;
} }
g_warning ("gtk_signal_handler_unblock(): could not find handler (%d)", anid); g_warning ("gtk_signal_handler_unblock(): could not find handler (%d)", an_id);
} }
void void
gtk_signal_handler_unblock_by_data (GtkObject *object, gtk_signal_handler_unblock_by_data (GtkObject *object,
gpointer data) gpointer data)
{ {
GtkHandler *tmp; GtkHandler *handler;
gint found_one; gint found_one;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
@ -759,17 +753,18 @@ gtk_signal_handler_unblock_by_data (GtkObject *object,
gtk_signal_init (); gtk_signal_init ();
found_one = FALSE; found_one = FALSE;
tmp = gtk_object_get_data (object, handler_key); handler = gtk_object_get_data (object, handler_key);
while (tmp) while (handler)
{ {
if (tmp->func_data == data) if (handler->func_data == data &&
handler->id > 0)
{ {
tmp->blocked = FALSE;
found_one = TRUE; found_one = TRUE;
handler->blocked = FALSE;
} }
tmp = tmp->next; handler = handler->next;
} }
if (!found_one) if (!found_one)
@ -779,18 +774,27 @@ gtk_signal_handler_unblock_by_data (GtkObject *object,
void void
gtk_signal_handlers_destroy (GtkObject *object) gtk_signal_handlers_destroy (GtkObject *object)
{ {
GtkHandler *list;
GtkHandler *handler; GtkHandler *handler;
list = gtk_object_get_data (object, handler_key); /* we make the "optimization" of destroying the first handler in the last
if (list) * place, since we don't want gtk_signal_handler_unref() to reset the objects
* handler_key data on each removal
*/
handler = gtk_object_get_data (object, handler_key);
if (handler)
{ {
while (list) handler = handler->next;
while (handler)
{ {
handler = list->next; GtkHandler *next;
gtk_signal_handler_unref (list, object);
list = handler; next = handler->next;
gtk_signal_handler_unref (handler, object);
handler = next;
} }
handler = gtk_object_get_data (object, handler_key);
gtk_signal_handler_unref (handler, object);
} }
} }
@ -870,13 +874,14 @@ gtk_signal_handler_new ()
handler->id = 0; handler->id = 0;
handler->ref_count = 1; handler->ref_count = 1;
handler->signal_type = 0; handler->signal_type = 0;
handler->object_signal = FALSE;
handler->blocked = FALSE; handler->blocked = FALSE;
handler->object_signal = FALSE;
handler->after = FALSE; handler->after = FALSE;
handler->no_marshal = FALSE; handler->no_marshal = FALSE;
handler->func = NULL; handler->func = NULL;
handler->func_data = NULL; handler->func_data = NULL;
handler->destroy_func = NULL; handler->destroy_func = NULL;
handler->prev = NULL;
handler->next = NULL; handler->next = NULL;
return handler; return handler;
@ -892,8 +897,6 @@ static void
gtk_signal_handler_unref (GtkHandler *handler, gtk_signal_handler_unref (GtkHandler *handler,
GtkObject *object) GtkObject *object)
{ {
GtkHandler *tmp;
if (!handler->ref_count) if (!handler->ref_count)
{ {
/* FIXME: i wanna get removed some when (maybe at gtk+-1.0?) */ /* FIXME: i wanna get removed some when (maybe at gtk+-1.0?) */
@ -909,13 +912,13 @@ gtk_signal_handler_unref (GtkHandler *handler,
else if (handler->destroy_func) else if (handler->destroy_func)
(* handler->destroy_func) (handler->func_data); (* handler->destroy_func) (handler->func_data);
tmp = gtk_object_get_data (object, handler_key);
while (tmp && tmp->next != handler) if (handler->prev)
tmp = tmp->next; handler->prev->next = handler->next;
if (tmp)
tmp->next = handler->next;
else else
gtk_object_set_data (object, handler_key, handler->next); gtk_object_set_data (object, handler_key, handler->next);
if (handler->next)
handler->next->prev = handler->prev;
g_mem_chunk_free (handler_mem_chunk, handler); g_mem_chunk_free (handler_mem_chunk, handler);
} }
@ -925,42 +928,39 @@ static void
gtk_signal_handler_insert (GtkObject *object, gtk_signal_handler_insert (GtkObject *object,
GtkHandler *handler) GtkHandler *handler)
{ {
GtkHandler *start;
GtkHandler *tmp; GtkHandler *tmp;
GtkHandler *prev;
/* FIXME: remove */ g_assert (handler->next == NULL);
start = gtk_object_get_data (object, handler_key); /* FIXME: remove */ g_assert (handler->prev == NULL);
if (!start)
{ tmp = gtk_object_get_data (object, handler_key);
gtk_object_set_data (object, handler_key, handler); if (!tmp)
} gtk_object_set_data (object, handler_key, handler);
else else
{ while (tmp)
prev = NULL; {
tmp = start; if (tmp->signal_type < handler->signal_type)
{
if (tmp->prev)
{
tmp->prev->next = handler;
handler->prev = tmp->prev;
}
else
gtk_object_set_data (object, handler_key, handler);
tmp->prev = handler;
handler->next = tmp;
break;
}
while (tmp) if (!tmp->next)
{ {
if (tmp->signal_type < handler->signal_type) tmp->next = handler;
{ handler->prev = tmp;
if (prev) break;
prev->next = handler; }
else tmp = tmp->next;
gtk_object_set_data (object, handler_key, handler); }
handler->next = tmp;
break;
}
if (!tmp->next)
{
tmp->next = handler;
break;
}
prev = tmp;
tmp = tmp->next;
}
}
} }
static void static void
@ -1134,9 +1134,7 @@ gtk_signal_connect_by_type (GtkObject *object,
handler->func = func; handler->func = func;
handler->func_data = func_data; handler->func_data = func_data;
handler->destroy_func = destroy_func; handler->destroy_func = destroy_func;
handler->after = after != FALSE;
if (after)
handler->after = TRUE;
handler->no_marshal = no_marshal; handler->no_marshal = no_marshal;
gtk_signal_handler_insert (object, handler); gtk_signal_handler_insert (object, handler);
@ -1240,18 +1238,16 @@ gtk_handlers_run (GtkHandler *handlers,
GtkHandlerInfo *info, GtkHandlerInfo *info,
gint after) gint after)
{ {
GtkHandler *handlers_next;
while (handlers) while (handlers)
{ {
/* REMOVE: if (!after) */ GtkHandler *handlers_next;
gtk_signal_handler_ref (handlers); gtk_signal_handler_ref (handlers);
if (handlers->signal_type != info->signal_type) if (handlers->signal_type != info->signal_type)
{ {
/* REMOVE: if (after) */
gtk_signal_handler_unref (handlers, info->object); gtk_signal_handler_unref (handlers, info->object);
break; return 0;
} }
if (!handlers->blocked && (handlers->after == after)) if (!handlers->blocked && (handlers->after == after))
@ -1281,17 +1277,16 @@ gtk_handlers_run (GtkHandler *handlers,
info->params, info->params,
info->param_types, info->param_types,
info->return_val); info->return_val);
if (gtk_emission_check (stop_emissions, info->object, if (gtk_emission_check (stop_emissions, info->object,
info->signal_type)) info->signal_type))
{ {
gtk_emission_remove (&stop_emissions, info->object, gtk_emission_remove (&stop_emissions, info->object,
info->signal_type); info->signal_type);
if (info->run_type & GTK_RUN_NO_RECURSE) if (info->run_type & GTK_RUN_NO_RECURSE)
gtk_emission_remove (&restart_emissions, info->object, gtk_emission_remove (&restart_emissions, info->object,
info->signal_type); info->signal_type);
/* REMOVE: if (after) */
gtk_signal_handler_unref (handlers, info->object); gtk_signal_handler_unref (handlers, info->object);
return DONE; return DONE;
} }
@ -1301,18 +1296,16 @@ gtk_handlers_run (GtkHandler *handlers,
{ {
gtk_emission_remove (&restart_emissions, info->object, gtk_emission_remove (&restart_emissions, info->object,
info->signal_type); info->signal_type);
/* REMOVE: if (after) */
gtk_signal_handler_unref (handlers, info->object); gtk_signal_handler_unref (handlers, info->object);
return RESTART; return RESTART;
} }
} }
handlers_next = handlers->next; handlers_next = handlers->next;
/* if (after) */ gtk_signal_handler_unref (handlers, info->object);
gtk_signal_handler_unref (handlers, info->object);
handlers = handlers_next; handlers = handlers_next;
} }
return 0; return 0;
} }

View File

@ -60,16 +60,17 @@ struct _GtkSignalQuery
struct _GtkHandler struct _GtkHandler
{ {
guint16 id; guint id : 28;
guint16 ref_count;
guint16 signal_type;
guint object_signal : 1;
guint blocked : 1; guint blocked : 1;
guint object_signal : 1;
guint after : 1; guint after : 1;
guint no_marshal : 1; guint no_marshal : 1;
guint16 ref_count;
guint16 signal_type;
GtkSignalFunc func; GtkSignalFunc func;
gpointer func_data; gpointer func_data;
GtkSignalDestroy destroy_func; GtkSignalDestroy destroy_func;
GtkHandler *prev;
GtkHandler *next; GtkHandler *next;
}; };