diff options
author | Simon Howard | 2006-09-09 16:48:09 +0000 |
---|---|---|
committer | Simon Howard | 2006-09-09 16:48:09 +0000 |
commit | bf2f9ea62a48d70496057e4f7e444e746e61f462 (patch) | |
tree | 3c0eec98180db1e174a791cce456f4a499673f0b | |
parent | 8040eba4c0f8a0996eb6487104646a0e5b261ee7 (diff) | |
download | chocolate-doom-bf2f9ea62a48d70496057e4f7e444e746e61f462.tar.gz chocolate-doom-bf2f9ea62a48d70496057e4f7e444e746e61f462.tar.bz2 chocolate-doom-bf2f9ea62a48d70496057e4f7e444e746e61f462.zip |
Add reference counts on callback tables so that if a callback destroys
the widget that owns the callback the program doesnt crash.
Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 599
-rw-r--r-- | textscreen/txt_widget.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/textscreen/txt_widget.c b/textscreen/txt_widget.c index 79528c7f..c66cf8dc 100644 --- a/textscreen/txt_widget.c +++ b/textscreen/txt_widget.c @@ -33,6 +33,7 @@ typedef struct struct txt_callback_table_s { + int refcount; txt_callback_t *callbacks; int num_callbacks; }; @@ -44,21 +45,34 @@ txt_callback_table_t *TXT_NewCallbackTable(void) table = malloc(sizeof(txt_callback_table_t)); table->callbacks = NULL; table->num_callbacks = 0; + table->refcount = 1; return table; } -void TXT_DestroyCallbackTable(txt_callback_table_t *table) +void TXT_RefCallbackTable(txt_callback_table_t *table) +{ + ++table->refcount; +} + +void TXT_UnrefCallbackTable(txt_callback_table_t *table) { int i; - for (i=0; i<table->num_callbacks; ++i) + --table->refcount; + + if (table->refcount == 0) { - free(table->callbacks[i].signal_name); - } + // No more references to this table + + for (i=0; i<table->num_callbacks; ++i) + { + free(table->callbacks[i].signal_name); + } - free(table->callbacks); - free(table); + free(table->callbacks); + free(table); + } } void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class) @@ -111,6 +125,11 @@ void TXT_EmitSignal(TXT_UNCAST_ARG(widget), char *signal_name) table = widget->callback_table; + // Don't destroy the table while we're searching through it + // (one of the callbacks may destroy this window) + + TXT_RefCallbackTable(table); + // Search the table for all callbacks with this name and invoke // the functions. @@ -121,6 +140,10 @@ void TXT_EmitSignal(TXT_UNCAST_ARG(widget), char *signal_name) table->callbacks[i].func(widget, table->callbacks[i].user_data); } } + + // Finished using the table + + TXT_UnrefCallbackTable(table); } void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget)) @@ -148,7 +171,7 @@ void TXT_DestroyWidget(TXT_UNCAST_ARG(widget)) TXT_CAST_ARG(txt_widget_t, widget); widget->widget_class->destructor(widget); - TXT_DestroyCallbackTable(widget->callback_table); + TXT_UnrefCallbackTable(widget->callback_table); free(widget); } |