static void naip_deleteList(void) { a3d_listitem_t* iter = a3d_list_head(glist); while(iter) { naip_node_t* node = (naip_node_t*) a3d_list_remove(glist, &iter); naip_node_delete(&node); } a3d_list_delete(&glist); }
void a3d_workq_delete(a3d_workq_t** _self) { // *_self can be null assert(_self); a3d_workq_t* self = *_self; if(self) { LOGD("debug"); pthread_mutex_lock(&self->mutex); // stop the workq thread self->state = A3D_WORKQ_STOP; pthread_cond_broadcast(&self->cond_pending); pthread_mutex_unlock(&self->mutex); int i; for(i = 0; i < self->thread_count; ++i) { pthread_join(self->threads[i], NULL); } free(self->threads); // destroy the queues // queue_active will be empty since the threads are stopped self->purge_id = A3D_WORKQ_PURGE; a3d_workq_purge(self); a3d_list_delete(&self->queue_active); a3d_list_delete(&self->queue_complete); a3d_list_delete(&self->queue_pending); // destroy the thread state pthread_cond_destroy(&self->cond_complete); pthread_cond_destroy(&self->cond_pending); pthread_mutex_destroy(&self->mutex); free(self); *_self = NULL; } }
void a3d_listbox_delete(a3d_listbox_t** _self) { assert(_self); a3d_listbox_t* self = *_self; if(self) { LOGD("debug"); a3d_list_delete(&self->list); a3d_widget_delete((a3d_widget_t**) _self); } }
const void* a3d_multimap_remove(a3d_multimap_t* self, a3d_multimapIter_t** _iter) { assert(self); assert(_iter); assert(*_iter); a3d_multimapIter_t* iter = *_iter; // remove item from list; a3d_list_t* list; list = (a3d_list_t*) a3d_hashmap_val(iter->hiter); const void* data = a3d_list_remove(list, &iter->item); // check if list is empty // or if next item is NULL if(a3d_list_empty(list)) { a3d_hashmap_remove(self->hash, &iter->hiter); a3d_list_delete(&list); if(iter->hiter) { list = (a3d_list_t*) a3d_hashmap_val(iter->hiter); iter->item = a3d_list_head(list); } } else if(iter->item == NULL) { iter->hiter = a3d_hashmap_next(iter->hiter); if(iter->hiter) { list = (a3d_list_t*) a3d_hashmap_val(iter->hiter); iter->item = a3d_list_head(list); } } // check for iteration end if(iter->hiter == NULL) { *_iter = NULL; } return data; }
a3d_workq_t* a3d_workq_new(void* owner, int thread_count, a3d_workqrun_fn run_fn, a3d_workqpurge_fn purge_fn) { // owner may be NULL assert(run_fn); assert(purge_fn); LOGD("debug"); a3d_workq_t* self = (a3d_workq_t*) malloc(sizeof(a3d_workq_t)); if(!self) { LOGE("malloc failed"); return NULL; } self->state = A3D_WORKQ_RUNNING; self->owner = owner; self->purge_id = 0; self->thread_count = thread_count; self->next_tid = 0; self->run_fn = run_fn; self->purge_fn = purge_fn; // PTHREAD_MUTEX_DEFAULT is not re-entrant if(pthread_mutex_init(&self->mutex, NULL) != 0) { LOGE("pthread_mutex_init failed"); goto fail_mutex_init; } if(pthread_cond_init(&self->cond_pending, NULL) != 0) { LOGE("pthread_cond_init failed"); goto fail_cond_pending; } if(pthread_cond_init(&self->cond_complete, NULL) != 0) { LOGE("pthread_cond_init failed"); goto fail_cond_complete; } self->queue_pending = a3d_list_new(); if(self->queue_pending == NULL) { goto fail_queue_pending; } self->queue_complete = a3d_list_new(); if(self->queue_complete == NULL) { goto fail_queue_complete; } self->queue_active = a3d_list_new(); if(self->queue_active == NULL) { goto fail_queue_active; } // alloc threads int sz = thread_count*sizeof(pthread_t); self->threads = (pthread_t*) malloc(sz); if(self->threads == NULL) { LOGE("malloc failed"); goto fail_threads; } // create threads pthread_mutex_lock(&self->mutex); int i; for(i = 0; i < thread_count; ++i) { if(pthread_create(&(self->threads[i]), NULL, a3d_workq_thread, (void*) self) != 0) { LOGE("pthread_create failed"); goto fail_pthread_create; } } pthread_mutex_unlock(&self->mutex); // success return self; // fail fail_pthread_create: self->state = A3D_WORKQ_STOP; pthread_mutex_unlock(&self->mutex); int j; for(j = 0; j < i; ++j) { pthread_join(self->threads[j], NULL); } free(self->threads); fail_threads: a3d_list_delete(&self->queue_active); fail_queue_active: a3d_list_delete(&self->queue_complete); fail_queue_complete: a3d_list_delete(&self->queue_pending); fail_queue_pending: pthread_cond_destroy(&self->cond_complete); fail_cond_complete: pthread_cond_destroy(&self->cond_pending); fail_cond_pending: pthread_mutex_destroy(&self->mutex); fail_mutex_init: free(self); return NULL; }
int a3d_multimap_add(a3d_multimap_t* self, const void* val, const char* key) { assert(self); assert(val); assert(key); a3d_listitem_t* item; // check if the list already exists a3d_hashmapIter_t iter; a3d_list_t* list; list = (a3d_list_t*) a3d_hashmap_find(self->hash, &iter, key); if(list && self->compare) { item = a3d_list_insertSorted(list, self->compare, val); if(item == NULL) { return 0; } return 1; } else if(list) { item = a3d_list_append(list, NULL, val); if(item == NULL) { return 0; } return 1; } // create a new list and add to hash list = a3d_list_new(); if(list == NULL) { return 0; } item = a3d_list_append(list, NULL, val); if(item == NULL) { goto fail_append; } if(a3d_hashmap_add(self->hash, (const void*) list, key) == 0) { goto fail_add; } // success return 1; // failure fail_add: a3d_list_remove(list, &item); fail_append: a3d_list_delete(&list); return 0; }