source: roaraudio/libroar/notify.c @ 4308:793061b59f6c

Last change on this file since 4308:793061b59f6c was 4308:793061b59f6c, checked in by phi, 14 years ago

added missing setting to zero after malloc

File size: 5.8 KB
Line 
1//notify.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38struct roar_subscriber {
39 uint32_t flags;
40 uint32_t event;
41 int emitter;
42 int target;
43 int target_type;
44 void (*cb)(struct roar_notify_core * core, struct roar_event * event, void * userdata);
45 void * userdata;
46 size_t refc;
47 unsigned int hash;
48// struct roar_subscriber * prev;
49 struct roar_subscriber * next;
50};
51
52struct roar_notify_core {
53 size_t refc;
54 size_t listc;
55 struct roar_subscriber ** lists;
56};
57
58#define _CKRCORE(ret) if ( core == NULL ) { roar_errno = ROAR_ERROR_INVAL; return (ret); }
59#define _CKICORE() _CKRCORE(-1)
60
61static unsigned int _hash_event (struct roar_notify_core * core, struct roar_event * event) {
62 unsigned int hash = 0;
63 unsigned int mask = core->listc - 1;
64
65 hash ^= event->event >>  0;
66 hash ^= event->event >>  8;
67 hash ^= event->event >> 16;
68 hash ^= event->event >> 24;
69
70 return hash & mask;
71}
72
73struct roar_notify_core * roar_notify_core_new(ssize_t lists) {
74 struct roar_notify_core * core = NULL;
75
76 switch (lists) {
77  case   1:
78  case   2:
79  case   4:
80  case   8:
81  case  16:
82  case  32:
83  case  64:
84  case 128:
85  case 256:
86    // they all are ok.
87   break;
88  case  -1:
89    // handle defult:
90    lists = 16;
91   break;
92  default:
93    roar_errno = ROAR_ERROR_INVAL;
94    return NULL;
95   break;
96 }
97
98 if ( (core = roar_mm_malloc(sizeof(struct roar_notify_core))) == NULL ) {
99  return NULL;
100 }
101
102 memset(core, 0, sizeof(struct roar_notify_core));
103
104 core->refc  = 1;
105 core->listc = lists;
106 core->lists = roar_mm_malloc(lists*sizeof(struct roar_subscriber *));
107
108 if ( core->lists == NULL ) {
109  roar_mm_free(core);
110  return NULL;
111 }
112
113 memset(core->lists, 0, lists*sizeof(struct roar_subscriber *));
114
115 return core;
116}
117
118int roar_notify_core_ref(struct roar_notify_core * core) {
119 _CKICORE();
120
121 core->refc++;
122
123 return 0;
124}
125
126int roar_notify_core_unref(struct roar_notify_core * core) {
127 struct roar_subscriber * cur, * next;
128 size_t i;
129
130 _CKICORE();
131
132 if ( core->refc == 0 ) {
133  ROAR_ERR("roar_notify_core_unref(core=%p): refc is zero, must be greater zero. resolving by setting to one.", core);
134  core->refc = 1;
135 }
136
137 core->refc--;
138
139 if ( core->refc > 0 ) {
140  return 0;
141 }
142
143 for (i = 0; i < core->listc; i++) {
144  cur = core->lists[i];
145  while (cur != NULL) {
146   next = cur->next;
147
148   roar_mm_free(cur);
149
150   cur = next;
151  }
152 }
153
154 roar_mm_free(core->lists);
155 roar_mm_free(core);
156 return 0;
157}
158
159struct roar_subscriber * roar_notify_core_subscribe(struct roar_notify_core * core, struct roar_event * event, void (*cb)(struct roar_notify_core * core, struct roar_event * event, void * userdata), void * userdata) {
160 struct roar_subscriber * subs = NULL;
161 struct roar_subscriber * cur, * old;
162
163 _CKRCORE(NULL);
164
165 if ( event == NULL || cb == NULL ) {
166  roar_errno = ROAR_ERROR_INVAL;
167  return NULL;
168 }
169
170 if ( (subs = roar_mm_malloc(sizeof(struct roar_subscriber))) == NULL ) {
171  return NULL;
172 }
173
174 memset(subs, 0, sizeof(struct roar_subscriber));
175
176 subs->flags       = 0;
177 subs->event       = event->event;
178 subs->emitter     = event->emitter;
179 subs->target      = event->target;
180 subs->target_type = event->target_type;
181 subs->cb          = cb;
182 subs->userdata    = userdata;
183 subs->refc        = 1;
184 subs->hash        = _hash_event(core, event);
185 subs->next        = NULL;
186
187 if ( (cur = core->lists[subs->hash]) == NULL ) {
188  core->lists[subs->hash] = subs;
189 } else {
190  old = cur;
191  while (cur != NULL) {
192   old = cur;
193   cur = cur->next;
194  }
195
196  old->next = subs;
197 }
198
199 return subs;
200}
201
202int roar_notify_core_unsubscribe(struct roar_notify_core * core, struct roar_subscriber * subscriber) {
203 struct roar_subscriber * cur, * old;
204
205 _CKICORE();
206
207 if ( subscriber ) {
208  roar_errno = ROAR_ERROR_INVAL;
209  return -1;
210 }
211
212 if ( (cur = core->lists[subscriber->hash]) == subscriber ) {
213  core->lists[subscriber->hash] = core->lists[subscriber->hash]->next;
214 } else {
215  old = NULL;
216  while (cur != NULL && cur != subscriber ) {
217   old = cur;
218   cur = cur->next;
219  }
220
221  if ( cur != subscriber )
222   return -1;
223
224  old->next = cur->next;
225  roar_mm_free(cur);
226 }
227
228 return 0;
229}
230
231int roar_notify_core_emit(struct roar_notify_core * core, struct roar_event * event) {
232 struct roar_subscriber * cur;
233
234 _CKICORE();
235
236 if ( event ) {
237  roar_errno = ROAR_ERROR_INVAL;
238  return -1;
239 }
240
241 cur = core->lists[_hash_event(core, event)];
242
243 while (cur != NULL) {
244  if ( cur->cb == NULL ) {
245   ROAR_ERR("roar_notify_core_emit(core=%p, event=%p): cur=%p, cb is set NULL, bad.", core, event, cur);
246  } else {
247   cur->cb(core, event, cur->userdata);
248  }
249  cur = cur->next;
250 }
251
252 return 0;
253}
254
255//ll
Note: See TracBrowser for help on using the repository browser.