int a3d_workq_cancel(a3d_workq_t* self, void* task) { assert(self); assert(task); LOGD("debug task=%p"); int status = A3D_WORKQ_ERROR; pthread_mutex_lock(&self->mutex); a3d_listitem_t* iter; if((iter = a3d_list_find(self->queue_pending, task, a3d_taskcmp_fn)) != NULL) { // cancel pending task a3d_workqnode_t* node; node = (a3d_workqnode_t*) a3d_list_remove(self->queue_pending, &iter); status = node->status; a3d_workqnode_delete(&node); } else { while((iter = a3d_list_find(self->queue_active, task, a3d_taskcmp_fn)) != NULL) { // must wait for active task to complete pthread_cond_wait(&self->cond_complete, &self->mutex); } if((iter = a3d_list_find(self->queue_complete, task, a3d_taskcmp_fn)) != NULL) { // cancel completed task a3d_workqnode_t* node; node = (a3d_workqnode_t*) a3d_list_remove(self->queue_complete, &iter); status = node->status; a3d_workqnode_delete(&node); } } pthread_mutex_unlock(&self->mutex); return status; }
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_textbox_clear(a3d_textbox_t* self) { assert(self); LOGD("debug"); a3d_listbox_t* listbox = (a3d_listbox_t*) self; a3d_listitem_t* iter = a3d_list_head(listbox->list); while(iter) { a3d_text_t* text; text = (a3d_text_t*) a3d_list_remove(listbox->list, &iter); a3d_text_delete(&text); } iter = a3d_list_head(self->strings); while(iter) { void* string = (void*) a3d_list_remove(self->strings, &iter); free(string); } a3d_widget_t* widget = (a3d_widget_t*) self; a3d_screen_dirty(widget->screen); }
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; }
static int a3d_layer_fade(a3d_widget_t* widget, float fade, float dt) { assert(widget); LOGD("debug"); int a; int animate = 0; a3d_layer_t* self = (a3d_layer_t*) widget; a3d_listitem_t* iter = a3d_list_head(self->list); a3d_widget_t* head = (a3d_widget_t*) a3d_list_peekhead(self->list); while(iter) { widget = (a3d_widget_t*) a3d_list_peekitem(iter); if((self->mode == A3D_LAYER_MODE_LAYERED) || (widget == head)) { a = a3d_widget_fade(widget, fade, dt); iter = a3d_list_next(iter); } else { // remove widget if fade-to-zero is complete a = a3d_widget_fade(widget, 0.0f, dt); if(a == 0) { a3d_list_remove(self->list, &iter); } else { iter = a3d_list_next(iter); } } animate |= a; } return animate; }
int a3d_workq_run(a3d_workq_t* self, void* task, int priority) { assert(self); assert(task); LOGD("debug task=%p, priority=%i", task, priority); pthread_mutex_lock(&self->mutex); // find the node containing the task or create a new one int status = A3D_WORKQ_ERROR; a3d_listitem_t* iter = NULL; a3d_listitem_t* pos = NULL; a3d_workqnode_t* tmp = NULL; a3d_workqnode_t* node = NULL; if((iter = a3d_list_find(self->queue_complete, task, a3d_taskcmp_fn)) != NULL) { // task completed node = (a3d_workqnode_t*) a3d_list_remove(self->queue_complete, &iter); status = node->status; a3d_workqnode_delete(&node); } else if((iter = a3d_list_find(self->queue_active, task, a3d_taskcmp_fn)) != NULL) { node = (a3d_workqnode_t*) a3d_list_peekitem(iter); node->purge_id = self->purge_id; status = A3D_WORKQ_PENDING; } else if((iter = a3d_list_find(self->queue_pending, task, a3d_taskcmp_fn)) != NULL) { node = (a3d_workqnode_t*) a3d_list_peekitem(iter); node->purge_id = self->purge_id; if(priority > node->priority) { // move up pos = a3d_list_prev(iter); while(pos) { tmp = (a3d_workqnode_t*) a3d_list_peekitem(pos); if(tmp->priority >= node->priority) { break; } pos = a3d_list_prev(pos); } if(pos) { // move after pos a3d_list_moven(self->queue_pending, iter, pos); } else { // move to head of list a3d_list_move(self->queue_pending, iter, NULL); } } else if(priority < node->priority) { // move down pos = a3d_list_next(iter); while(pos) { tmp = (a3d_workqnode_t*) a3d_list_peekitem(pos); if(tmp->priority < node->priority) { break; } pos = a3d_list_next(pos); } if(pos) { // move before pos a3d_list_move(self->queue_pending, iter, pos); } else { // move to tail of list a3d_list_moven(self->queue_pending, iter, NULL); } } node->priority = priority; status = A3D_WORKQ_PENDING; } else { // create new node node = a3d_workqnode_new(task, self->purge_id, priority); if(node == NULL) { goto fail_node; } else { // find the insert position pos = a3d_list_tail(self->queue_pending); while(pos) { tmp = (a3d_workqnode_t*) a3d_list_peekitem(pos); if(tmp->priority >= node->priority) { break; } pos = a3d_list_prev(pos); } if(pos) { // append after pos if(a3d_list_append(self->queue_pending, pos, (const void*) node) == NULL) { goto fail_queue; } } else { // insert at head of queue // first item or highest priority if(a3d_list_insert(self->queue_pending, NULL, (const void*) node) == NULL) { goto fail_queue; } } status = A3D_WORKQ_PENDING; // wake up workq thread pthread_cond_signal(&self->cond_pending); } } pthread_mutex_unlock(&self->mutex); // success return status; // failure fail_queue: a3d_workqnode_delete(&node); fail_node: pthread_mutex_unlock(&self->mutex); return A3D_WORKQ_ERROR; }
void a3d_workq_purge(a3d_workq_t* self) { assert(self); LOGD("debug"); pthread_mutex_lock(&self->mutex); // purge the pending queue a3d_listitem_t* iter = a3d_list_head(self->queue_pending); while(iter) { a3d_workqnode_t* node; node = (a3d_workqnode_t*) a3d_list_peekitem(iter); if(node->purge_id != self->purge_id) { a3d_list_remove(self->queue_pending, &iter); (*self->purge_fn)(self->owner, node->task, node->status); a3d_workqnode_delete(&node); } else { iter = a3d_list_next(iter); } } // purge the active queue (non-blocking) iter = a3d_list_head(self->queue_active); while(iter) { a3d_workqnode_t* node; node = (a3d_workqnode_t*) a3d_list_peekitem(iter); if(node->purge_id != self->purge_id) { node->purge_id = A3D_WORKQ_PURGE; } iter = a3d_list_next(iter); } // purge the complete queue iter = a3d_list_head(self->queue_complete); while(iter) { a3d_workqnode_t* node; node = (a3d_workqnode_t*) a3d_list_peekitem(iter); if((node->purge_id != self->purge_id) || (node->purge_id == A3D_WORKQ_PURGE)) { a3d_list_remove(self->queue_complete, &iter); (*self->purge_fn)(self->owner, node->task, node->status); a3d_workqnode_delete(&node); } else { iter = a3d_list_next(iter); } } // swap the purge id if(self->purge_id != A3D_WORKQ_PURGE) { self->purge_id = 1 - self->purge_id; } pthread_mutex_unlock(&self->mutex); }
static void a3d_textbox_reflow(a3d_widget_t* widget, float w, float h) { assert(widget); LOGD("debug w=%f, h=%f", w, h); a3d_textbox_t* self = (a3d_textbox_t*) widget; // reflow text when changes occur if((self->dirty == 0) && (self->last_w == w) && (self->last_h == h)) { return; } self->dirty = 0; self->last_w = w; self->last_h = h; // determine maxi a3d_font_t* font = a3d_screen_font(widget->screen); float aspect = a3d_font_aspectRatio(font); float size = a3d_screen_layoutText(widget->screen, self->style_text); int maxi = (int) (w/(aspect*size)) - 1; // maxi does not include null character // but max_len does // limit to max_len if((maxi >= self->max_len) || (maxi == 0)) { maxi = self->max_len - 1; } // clear the text a3d_listbox_t* listbox = (a3d_listbox_t*) self; a3d_listitem_t* iter = a3d_list_head(listbox->list); while(iter) { a3d_text_t* text; text = (a3d_text_t*) a3d_list_remove(listbox->list, &iter); a3d_text_delete(&text); } // initialize parser char tok[256]; char dst[256]; int srci = 0; int toki = 0; int dsti = 0; int type = A3D_TOKEN_END; // reflow the string(s) iter = a3d_list_head(self->strings); while(iter) { const char* src = (const char*) a3d_list_peekitem(iter); srci = 0; type = getToken(src, tok, &srci, &toki); while(type != A3D_TOKEN_END) { if(type == A3D_TOKEN_BREAK) { if(dsti > 0) { a3d_textbox_printText(self, dst); a3d_textbox_printText(self, ""); } else { a3d_textbox_printText(self, ""); } dsti = 0; break; } if(dsti == 0) { strncpy(dst, tok, 256); dst[255] = '\0'; dsti = toki; } else { if(dsti + toki + 1 <= maxi) { strcat(dst, " "); strcat(dst, tok); dst[255] = '\0'; dsti += toki + 1; } else { a3d_textbox_printText(self, dst); strncpy(dst, tok, 256); dst[255] = '\0'; dsti = toki; } } type = getToken(src, tok, &srci, &toki); } iter = a3d_list_next(iter); } if(dsti > 0) { a3d_textbox_printText(self, dst); } }
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; }