Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
hook.c
Go to the documentation of this file.
1 /*
2  * hook.c
3  * Copyright 2011 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions, and the following disclaimer in the documentation
13  * provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <glib.h>
21 #include <pthread.h>
22 
23 #include "core.h"
24 #include "hook.h"
25 
26 typedef struct {
28  void * user;
31 } HookItem;
32 
33 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
34 static GHashTable * hooks; /* of (GQueue of (HookItem *) *) */
35 
36 /* str_unref() may be a macro */
37 static void str_unref_cb (void * str)
38 {
39  str_unref (str);
40 }
41 
42 EXPORT void hook_associate (const char * name, HookFunction func, void * user)
43 {
44  pthread_mutex_lock (& mutex);
45 
46  if (! hooks)
47  hooks = g_hash_table_new_full (g_str_hash, g_str_equal, str_unref_cb,
48  (GDestroyNotify) g_queue_free);
49 
50  GQueue * list = g_hash_table_lookup (hooks, name);
51 
52  if (! list)
53  g_hash_table_insert (hooks, str_get (name), list = g_queue_new ());
54 
55  HookItem * item = g_slice_new (HookItem);
56  item->func = func;
57  item->user = user;
58  item->lock_count = 0;
59  item->remove_flag = FALSE;
60 
61  g_queue_push_tail (list, item);
62 
63  pthread_mutex_unlock (& mutex);
64 }
65 
66 EXPORT void hook_dissociate_full (const char * name, HookFunction func, void * user)
67 {
68  pthread_mutex_lock (& mutex);
69 
70  if (! hooks)
71  goto DONE;
72 
73  GQueue * list = g_hash_table_lookup (hooks, name);
74 
75  if (! list)
76  goto DONE;
77 
78  for (GList * node = list->head; node;)
79  {
80  HookItem * item = node->data;
81  GList * next = node->next;
82 
83  if (item->func == func && (! user || item->user == user))
84  {
85  if (item->lock_count)
86  item->remove_flag = TRUE;
87  else
88  {
89  g_queue_delete_link (list, node);
90  g_slice_free (HookItem, item);
91  }
92  }
93 
94  node = next;
95  }
96 
97  if (! list->head)
98  g_hash_table_remove (hooks, name);
99 
100 DONE:
101  pthread_mutex_unlock (& mutex);
102 }
103 
104 EXPORT void hook_call (const char * name, void * data)
105 {
106  pthread_mutex_lock (& mutex);
107 
108  if (! hooks)
109  goto DONE;
110 
111  GQueue * list = g_hash_table_lookup (hooks, name);
112 
113  if (! list)
114  goto DONE;
115 
116  for (GList * node = list->head; node;)
117  {
118  HookItem * item = node->data;
119 
120  if (! item->remove_flag)
121  {
122  item->lock_count ++;
123  pthread_mutex_unlock (& mutex);
124 
125  item->func (data, item->user);
126 
127  pthread_mutex_lock (& mutex);
128  item->lock_count --;
129  }
130 
131  GList * next = node->next;
132 
133  if (item->remove_flag && ! item->lock_count)
134  {
135  g_queue_delete_link (list, node);
136  g_slice_free (HookItem, item);
137  }
138 
139  node = next;
140  }
141 
142  if (! list->head)
143  g_hash_table_remove (hooks, name);
144 
145 DONE:
146  pthread_mutex_unlock (& mutex);
147 }
static pthread_mutex_t mutex
Definition: hook.c:33
EXPORT void hook_dissociate_full(const char *name, HookFunction func, void *user)
Definition: hook.c:66
static void str_unref_cb(void *str)
Definition: hook.c:37
Definition: hook.c:26
void(* HookFunction)(void *data, void *user)
Definition: hook.h:23
EXPORT void hook_associate(const char *name, HookFunction func, void *user)
Definition: hook.c:42
#define FALSE
Definition: core.h:37
Index Index bool_t
Definition: playlist-api.h:122
static GHashTable * hooks
Definition: hook.c:34
const char * name
Definition: plugin-init.c:38
#define TRUE
Definition: core.h:39
func
Definition: plugins-api.h:41
void str_unref(char *str)
Definition: strpool.c:131
bool_t remove_flag
Definition: hook.c:30
void * user
Definition: hook.c:28
HookFunction func
Definition: hook.c:27
EXPORT void hook_call(const char *name, void *data)
Definition: hook.c:104
int lock_count
Definition: hook.c:29
char * str_get(const char *str)
Definition: strpool.c:68