Changeset 4305:214fe3e67d09 in roaraudio for libroar/notify.c
- Timestamp:
- 09/07/10 03:40:15 (14 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libroar/notify.c
r4304 r4305 45 45 void * userdata; 46 46 size_t refc; 47 unsigned int hash; 48 // struct roar_subscriber * prev; 47 49 struct roar_subscriber * next; 48 50 }; 49 51 52 struct 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 61 static 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 73 struct 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 return core; 114 } 115 116 int roar_notify_core_ref(struct roar_notify_core * core) { 117 _CKICORE(); 118 119 core->refc++; 120 121 return 0; 122 } 123 124 int roar_notify_core_unref(struct roar_notify_core * core) { 125 struct roar_subscriber * cur, * next; 126 size_t i; 127 128 _CKICORE(); 129 130 if ( core->refc == 0 ) { 131 ROAR_ERR("roar_notify_core_unref(core=%p): refc is zero, must be greater zero. resolving by setting to one.", core); 132 core->refc = 1; 133 } 134 135 core->refc--; 136 137 if ( core->refc > 0 ) { 138 return 0; 139 } 140 141 for (i = 0; i < core->listc; i++) { 142 cur = core->lists[i]; 143 while (cur != NULL) { 144 next = cur->next; 145 146 roar_mm_free(cur); 147 148 cur = next; 149 } 150 } 151 152 roar_mm_free(core->lists); 153 roar_mm_free(core); 154 return 0; 155 } 156 157 struct roar_subscriber * roar_notify_core_subscribe(struct roar_notify_core * core, struct roar_event * event, void (*cb)(struct roar_event * event, void * userdata), void * userdata) { 158 struct roar_subscriber * subs = NULL; 159 struct roar_subscriber * cur, * old; 160 161 _CKRCORE(NULL); 162 163 if ( event == NULL || cb == NULL ) { 164 roar_errno = ROAR_ERROR_INVAL; 165 return NULL; 166 } 167 168 if ( (subs = roar_mm_malloc(sizeof(struct roar_subscriber))) == NULL ) { 169 return NULL; 170 } 171 172 memset(subs, 0, sizeof(struct roar_subscriber)); 173 174 subs->flags = 0; 175 subs->event = event->event; 176 subs->emitter = event->emitter; 177 subs->target = event->target; 178 subs->target_type = event->target_type; 179 subs->cb = cb; 180 subs->userdata = userdata; 181 subs->refc = 1; 182 subs->hash = _hash_event(core, event); 183 subs->next = NULL; 184 185 if ( (cur = core->lists[subs->hash]) == NULL ) { 186 core->lists[subs->hash] = subs; 187 } else { 188 old = cur; 189 while (cur != NULL) { 190 old = cur; 191 cur = cur->next; 192 } 193 194 old->next = subs; 195 } 196 197 return subs; 198 } 199 200 int roar_notify_core_unsubscribe(struct roar_notify_core * core, struct roar_subscriber * subscriber) { 201 struct roar_subscriber * cur, * old; 202 203 _CKICORE(); 204 205 if ( subscriber ) { 206 roar_errno = ROAR_ERROR_INVAL; 207 return -1; 208 } 209 210 if ( (cur = core->lists[subscriber->hash]) == subscriber ) { 211 core->lists[subscriber->hash] = core->lists[subscriber->hash]->next; 212 } else { 213 old = NULL; 214 while (cur != NULL && cur != subscriber ) { 215 old = cur; 216 cur = cur->next; 217 } 218 219 if ( cur != subscriber ) 220 return -1; 221 222 old->next = cur->next; 223 roar_mm_free(cur); 224 } 225 226 return 0; 227 } 228 229 int roar_notify_core_emit(struct roar_notify_core * core, struct roar_event * event) { 230 struct roar_subscriber * cur; 231 232 _CKICORE(); 233 234 if ( event ) { 235 roar_errno = ROAR_ERROR_INVAL; 236 return -1; 237 } 238 239 cur = core->lists[_hash_event(core, event)]; 240 241 while (cur != NULL) { 242 if ( cur->cb == NULL ) { 243 ROAR_ERR("roar_notify_core_emit(core=%p, event=%p): cur=%p, cb is set NULL, bad.", core, event, cur); 244 } else { 245 cur->cb(event, cur->userdata); 246 } 247 cur = cur->next; 248 } 249 250 return 0; 251 } 252 50 253 //ll
Note: See TracChangeset
for help on using the changeset viewer.