Changeset 4305:214fe3e67d09 in roaraudio for libroar/notify.c


Ignore:
Timestamp:
09/07/10 03:40:15 (14 years ago)
Author:
phi
Branch:
default
Phase:
public
Message:

implemented most of the notify logic

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libroar/notify.c

    r4304 r4305  
    4545 void * userdata; 
    4646 size_t refc; 
     47 unsigned int hash; 
     48// struct roar_subscriber * prev; 
    4749 struct roar_subscriber * next; 
    4850}; 
    4951 
     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 return core; 
     114} 
     115 
     116int roar_notify_core_ref(struct roar_notify_core * core) { 
     117 _CKICORE(); 
     118 
     119 core->refc++; 
     120 
     121 return 0; 
     122} 
     123 
     124int 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 
     157struct 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 
     200int 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 
     229int 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 
    50253//ll 
Note: See TracChangeset for help on using the changeset viewer.