X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Fcore%2Fsignals.c;fp=apps%2Firssi%2Fsrc%2Fcore%2Fsignals.c;h=0000000000000000000000000000000000000000;hb=72c2de619079457f7a68100eb13385275a424a23;hp=316424522f7f49e9efe122584f591729586b3ce6;hpb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;p=runtime.git diff --git a/apps/irssi/src/core/signals.c b/apps/irssi/src/core/signals.c deleted file mode 100644 index 31642452..00000000 --- a/apps/irssi/src/core/signals.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - signals.c : irssi - - Copyright (C) 1999-2002 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "module.h" -#include "signals.h" -#include "modules.h" - -typedef struct _SignalHook { - struct _SignalHook *next; - - int priority; - const char *module; - SIGNAL_FUNC func; - void *user_data; -} SignalHook; - -typedef struct { - int id; /* signal id */ - int refcount; - - int emitting; /* signal is being emitted */ - int stop_emit; /* this signal was stopped */ - int continue_emit; /* this signal emit was continued elsewhere */ - int remove_count; /* hooks were removed from signal */ - - SignalHook *hooks; -} Signal; - -void *signal_user_data; - -static GHashTable *signals; -static Signal *current_emitted_signal; -static SignalHook *current_emitted_hook; - -#define signal_ref(signal) ++(signal)->refcount -#define signal_unref(signal) (signal_unref_full(signal, TRUE)) - -static int signal_unref_full(Signal *rec, int remove) -{ - g_assert(rec->refcount > 0); - - if (--rec->refcount != 0) - return TRUE; - - /* remove whole signal from memory */ - if (rec->hooks != NULL) { - g_error("signal_unref(%s) : BUG - hook list wasn't empty", - signal_get_id_str(rec->id)); - } - - if (remove) - g_hash_table_remove(signals, GINT_TO_POINTER(rec->id)); - g_free(rec); - - return FALSE; -} - -static void signal_hash_ref(void *key, Signal *rec) -{ - signal_ref(rec); -} - -static int signal_hash_unref(void *key, Signal *rec) -{ - return !signal_unref_full(rec, FALSE); -} - -void signal_add_full(const char *module, int priority, - const char *signal, SIGNAL_FUNC func, void *user_data) -{ - signal_add_full_id(module, priority, signal_get_uniq_id(signal), - func, user_data); -} - -/* bind a signal */ -void signal_add_full_id(const char *module, int priority, - int signal_id, SIGNAL_FUNC func, void *user_data) -{ - Signal *signal; - SignalHook *hook, **tmp; - - g_return_if_fail(signal_id >= 0); - g_return_if_fail(func != NULL); - - signal = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id)); - if (signal == NULL) { - /* new signal */ - signal = g_new0(Signal, 1); - signal->id = signal_id; - g_hash_table_insert(signals, GINT_TO_POINTER(signal_id), signal); - } - - hook = g_new0(SignalHook, 1); - hook->priority = priority; - hook->module = module; - hook->func = func; - hook->user_data = user_data; - - /* insert signal to proper position in list */ - for (tmp = &signal->hooks; ; tmp = &(*tmp)->next) { - if (*tmp == NULL) { - /* last in list */ - *tmp = hook; - break; - } else if (priority <= (*tmp)->priority) { - /* insert before others with same priority */ - hook->next = *tmp; - *tmp = hook; - break; - } - } - - signal_ref(signal); -} - -static void signal_remove_hook(Signal *rec, SignalHook **hook_pos) -{ - SignalHook *hook; - - hook = *hook_pos; - *hook_pos = hook->next; - - g_free(hook); - - signal_unref(rec); -} - -/* Remove function from signal's emit list */ -static int signal_remove_func(Signal *rec, SIGNAL_FUNC func, void *user_data) -{ - SignalHook **hook; - - for (hook = &rec->hooks; *hook != NULL; hook = &(*hook)->next) { - if ((*hook)->func == func && (*hook)->user_data == user_data) { - if (rec->emitting) { - /* mark it removed after emitting is done */ - (*hook)->func = NULL; - rec->remove_count++; - } else { - /* remove the function from emit list */ - signal_remove_hook(rec, hook); - } - return TRUE; - } - } - - return FALSE; -} - -void signal_remove_id(int signal_id, SIGNAL_FUNC func, void *user_data) -{ - Signal *rec; - - g_return_if_fail(signal_id >= 0); - g_return_if_fail(func != NULL); - - rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id)); - if (rec != NULL) - signal_remove_func(rec, func, user_data); -} - -/* unbind signal */ -void signal_remove_full(const char *signal, SIGNAL_FUNC func, void *user_data) -{ - g_return_if_fail(signal != NULL); - - signal_remove_id(signal_get_uniq_id(signal), func, user_data); -} - -static void signal_hooks_clean(Signal *rec) -{ - SignalHook **hook, **next; - int count; - - count = rec->remove_count; - rec->remove_count = 0; - - for (hook = &rec->hooks; *hook != NULL; hook = next) { - next = &(*hook)->next; - - if ((*hook)->func == NULL) { - next = hook; - signal_remove_hook(rec, hook); - - if (--count == 0) - break; - } - } -} - -static int signal_emit_real(Signal *rec, int params, va_list va, - SignalHook *first_hook) -{ - const void *arglist[SIGNAL_MAX_ARGUMENTS]; - Signal *prev_emitted_signal; - SignalHook *hook, *prev_emitted_hook; - int i, stopped, stop_emit_count, continue_emit_count; - - for (i = 0; i < SIGNAL_MAX_ARGUMENTS; i++) - arglist[i] = i >= params ? NULL : va_arg(va, const void *); - - /* signal_stop_by_name("signal"); signal_emit("signal", ...); - fails if we compare rec->stop_emit against 0. */ - stop_emit_count = rec->stop_emit; - continue_emit_count = rec->continue_emit; - - signal_ref(rec); - - stopped = FALSE; - rec->emitting++; - - prev_emitted_signal = current_emitted_signal; - prev_emitted_hook = current_emitted_hook; - current_emitted_signal = rec; - - for (hook = first_hook; hook != NULL; hook = hook->next) { - if (hook->func == NULL) - continue; /* removed */ - - current_emitted_hook = hook; -#if SIGNAL_MAX_ARGUMENTS != 6 -# error SIGNAL_MAX_ARGUMENTS changed - update code -#endif - signal_user_data = hook->user_data; - hook->func(arglist[0], arglist[1], arglist[2], arglist[3], - arglist[4], arglist[5]); - - if (rec->continue_emit != continue_emit_count) - rec->continue_emit--; - - if (rec->stop_emit != stop_emit_count) { - stopped = TRUE; - rec->stop_emit--; - break; - } - } - - current_emitted_signal = prev_emitted_signal; - current_emitted_hook = prev_emitted_hook; - - rec->emitting--; - signal_user_data = NULL; - - if (!rec->emitting) { - g_assert(rec->stop_emit == 0); - g_assert(rec->continue_emit == 0); - - if (rec->remove_count > 0) - signal_hooks_clean(rec); - } - - signal_unref(rec); - return stopped; -} - -int signal_emit(const char *signal, int params, ...) -{ - Signal *rec; - va_list va; - int signal_id; - - g_return_val_if_fail(params >= 0 && params <= SIGNAL_MAX_ARGUMENTS, FALSE); - - signal_id = signal_get_uniq_id(signal); - - rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id)); - if (rec != NULL) { - va_start(va, params); - signal_emit_real(rec, params, va, rec->hooks); - va_end(va); - } - - return rec != NULL; -} - -int signal_emit_id(int signal_id, int params, ...) -{ - Signal *rec; - va_list va; - - g_return_val_if_fail(signal_id >= 0, FALSE); - g_return_val_if_fail(params >= 0 && params <= SIGNAL_MAX_ARGUMENTS, FALSE); - - rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id)); - if (rec != NULL) { - va_start(va, params); - signal_emit_real(rec, params, va, rec->hooks); - va_end(va); - } - - return rec != NULL; -} - -void signal_continue(int params, ...) -{ - Signal *rec; - va_list va; - - rec = current_emitted_signal; - if (rec == NULL || rec->emitting <= rec->continue_emit) - g_warning("signal_continue() : no signals are being emitted currently"); - else { - va_start(va, params); - - /* stop the signal */ - if (rec->emitting > rec->stop_emit) - rec->stop_emit++; - - /* re-emit */ - rec->continue_emit++; - signal_emit_real(rec, params, va, current_emitted_hook->next); - va_end(va); - } -} - -/* stop the current ongoing signal emission */ -void signal_stop(void) -{ - Signal *rec; - - rec = current_emitted_signal; - if (rec == NULL) - g_warning("signal_stop() : no signals are being emitted currently"); - else if (rec->emitting > rec->stop_emit) - rec->stop_emit++; -} - -/* stop ongoing signal emission by signal name */ -void signal_stop_by_name(const char *signal) -{ - Signal *rec; - int signal_id; - - signal_id = signal_get_uniq_id(signal); - rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id)); - if (rec == NULL) - g_warning("signal_stop_by_name() : unknown signal \"%s\"", signal); - else if (rec->emitting > rec->stop_emit) - rec->stop_emit++; -} - -/* return the name of the signal that is currently being emitted */ -const char *signal_get_emitted(void) -{ - return signal_get_id_str(signal_get_emitted_id()); -} - -/* return the ID of the signal that is currently being emitted */ -int signal_get_emitted_id(void) -{ - Signal *rec; - - rec = current_emitted_signal; - g_return_val_if_fail(rec != NULL, -1); - return rec->id; -} - -/* return TRUE if specified signal was stopped */ -int signal_is_stopped(int signal_id) -{ - Signal *rec; - - rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id)); - g_return_val_if_fail(rec != NULL, FALSE); - - return rec->emitting <= rec->stop_emit; -} - -static void signal_remove_module(void *signal, Signal *rec, - const char *module) -{ - SignalHook **hook, **next; - - for (hook = &rec->hooks; *hook != NULL; hook = next) { - next = &(*hook)->next; - - if (strcasecmp((*hook)->module, module) == 0) { - next = hook; - signal_remove_hook(rec, hook); - } - } -} - -/* remove all signals that belong to `module' */ -void signals_remove_module(const char *module) -{ - g_return_if_fail(module != NULL); - - g_hash_table_foreach(signals, (GHFunc) signal_hash_ref, NULL); - g_hash_table_foreach(signals, (GHFunc) signal_remove_module, - (void *) module); - g_hash_table_foreach_remove(signals, (GHRFunc) signal_hash_unref, NULL); -} - -void signals_init(void) -{ - signals = g_hash_table_new(NULL, NULL); -} - -static void signal_free(void *key, Signal *rec) -{ - /* refcount-1 because we just referenced it ourself */ - g_warning("signal_free(%s) : signal still has %d references:", - signal_get_id_str(rec->id), rec->refcount-1); - - while (rec->hooks != NULL) { - g_warning(" - module '%s' function %p", - rec->hooks->module, rec->hooks->func); - - signal_remove_hook(rec, &rec->hooks); - } -} - -void signals_deinit(void) -{ - g_hash_table_foreach(signals, (GHFunc) signal_hash_ref, NULL); - g_hash_table_foreach(signals, (GHFunc) signal_free, NULL); - g_hash_table_foreach_remove(signals, (GHRFunc) signal_hash_unref, NULL); - g_hash_table_destroy(signals); - - module_uniq_destroy("signals"); -}