00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <glib.h>
00021 #include <pthread.h>
00022 #include <string.h>
00023
00024 #include "config.h"
00025 #include "core.h"
00026 #include "hook.h"
00027
00028 typedef struct {
00029 HookFunction func;
00030 void * user;
00031 } HookItem;
00032
00033 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
00034 static GHashTable * hooks;
00035
00036
00037 static void str_unref_cb (void * str)
00038 {
00039 str_unref (str);
00040 }
00041
00042 EXPORT void hook_associate (const char * name, HookFunction func, void * user)
00043 {
00044 pthread_mutex_lock (& mutex);
00045
00046 if (! hooks)
00047 hooks = g_hash_table_new_full (g_str_hash, g_str_equal, str_unref_cb, NULL);
00048
00049 HookItem * item = g_slice_new (HookItem);
00050 item->func = func;
00051 item->user = user;
00052
00053 GList * items = g_hash_table_lookup (hooks, name);
00054 items = g_list_prepend (items, item);
00055 g_hash_table_insert (hooks, str_get (name), items);
00056
00057 pthread_mutex_unlock (& mutex);
00058 }
00059
00060 EXPORT void hook_dissociate_full (const char * name, HookFunction func, void * user)
00061 {
00062 pthread_mutex_lock (& mutex);
00063
00064 if (! hooks)
00065 goto DONE;
00066
00067 GList * items = g_hash_table_lookup (hooks, name);
00068
00069 GList * node = items;
00070 while (node)
00071 {
00072 HookItem * item = node->data;
00073 GList * next = node->next;
00074
00075 if (item->func == func && (! user || item->user == user))
00076 {
00077 items = g_list_delete_link (items, node);
00078 g_slice_free (HookItem, item);
00079 }
00080
00081 node = next;
00082 }
00083
00084 if (items)
00085 g_hash_table_insert (hooks, str_get (name), items);
00086 else
00087 g_hash_table_remove (hooks, name);
00088
00089 DONE:
00090 pthread_mutex_unlock (& mutex);
00091 }
00092
00093 EXPORT void hook_call (const char * name, void * data)
00094 {
00095 pthread_mutex_lock (& mutex);
00096
00097 if (! hooks)
00098 goto DONE;
00099
00100 GList * node = g_hash_table_lookup (hooks, name);
00101
00102 for (; node; node = node->next)
00103 {
00104 HookItem * item = node->data;
00105 item->func (data, item->user);
00106 }
00107
00108 DONE:
00109 pthread_mutex_unlock (& mutex);
00110 }