static inline void msgque_sync_pop(ptq_t ptq,int32_t timeout) { msgque_t que = ptq->que; mutex_lock(que->mtx); if(timeout > 0){ if(llist_is_empty(&que->share_que) && timeout){ uint64_t end = GetSystemMs64() + (uint64_t)timeout; dlist_push(&que->blocks,&ptq->read_que.bnode); do{ if(0 != condition_timedwait(ptq->cond,que->mtx,timeout)){ //timeout dlist_remove(&ptq->read_que.bnode); break; } uint64_t l_now = GetSystemMs64(); if(l_now < end) timeout = end - l_now; else break;//timeout }while(llist_is_empty(&que->share_que)); } } /*else if(llist_is_empty(&que->share_que)) { dlist_push(&que->blocks,&ptq->read_que.bnode); do{ condition_wait(ptq->cond,que->mtx); }while(llist_is_empty(&que->share_que)); }*/ if(!llist_is_empty(&que->share_que)) llist_swap(&ptq->local_que,&que->share_que); mutex_unlock(que->mtx); }
TESTS_BEGIN TEST (basic) { LLIST_AUTO (node1); llist node2; llist_init (&node2); printf ("%d\n", llist_is_empty (&node1)); printf ("%d\n", llist_is_empty (&node2)); }
static inline void _flush_local(ptq_t ptq) { assert(ptq->mode == MSGQ_WRITE); if(ptq->mode != MSGQ_WRITE)return; if(llist_is_empty(&ptq->local_que))return; msgque_sync_push(ptq); }
//push消息并执行同步操作 static inline void msgque_sync_push(ptq_t ptq) { assert(ptq->mode == MSGQ_WRITE); if(ptq->mode != MSGQ_WRITE) return; msgque_t que = ptq->que; mutex_lock(que->mtx); uint8_t empty = llist_is_empty(&que->share_que); llist_swap(&que->share_que,&ptq->local_que); if(empty){ struct dnode *l = dlist_pop(&que->blocks); if(l){ //if there is a block per_thread_struct wake it up ptq_t block_ptq = (ptq_t)l; mutex_unlock(que->mtx); condition_signal(block_ptq->cond); } } //对所有在can_interrupt中的元素调用回调 while(!dlist_empty(&que->can_interrupt)) { ptq_t ptq = (ptq_t)dlist_pop(&que->can_interrupt); ptq->read_que.notify_function(ptq->read_que.ud); } mutex_unlock(que->mtx); }
int32_t msgque_len(msgque_t que,int32_t timeout) { ptq_t ptq = get_per_thread_que(que,MSGQ_READ); assert(ptq->mode == MSGQ_READ); if(ptq->mode != MSGQ_READ)return -1; if(!llist_is_empty(&ptq->local_que)) timeout = 0; msgque_sync_pop(ptq,timeout); return llist_size(&ptq->local_que); }
LumieraConfigLookupentry lumiera_config_lookupentry_destroy (LumieraConfigLookupentry self) { TRACE (configlookup_dbg); if (self) { REQUIRE (llist_is_empty (&self->configitems), "lookup node still in use"); lumiera_free (self->full_key); } return self; }
int8_t msgque_get(msgque_t que,lnode **msg,int32_t timeout) { ptq_t ptq = get_per_thread_que(que,MSGQ_READ); assert(ptq->mode == MSGQ_READ); if(ptq->mode != MSGQ_READ)return -1; //本地无消息,执行同步 if(llist_is_empty(&ptq->local_que)) msgque_sync_pop(ptq,timeout); *msg = LLIST_POP(lnode*,&ptq->local_que); return 0; }
LumieraConfigitem lumiera_config_lookup_item_tail_find (LumieraConfigLookup self, const char* key) { TRACE (configlookup_dbg, "%s", key); LumieraConfigLookupentry entry = lumiera_config_lookup_find (self, key); if (entry && !llist_is_empty (&entry->configitems)) return LLIST_TO_STRUCTP (llist_tail (&entry->configitems), lumiera_configitem, lookup); return NULL; }
LumieraConfigitem lumiera_config_lookup_remove (LumieraConfigLookup self, LumieraConfigitem item) { TRACE (configlookup_dbg, "%s", item->line); REQUIRE (!llist_is_empty (&item->lookup), "item is not in a lookup"); if (llist_is_single (&item->lookup)) { /* last item in lookup, remove it from the splay tree */ LumieraConfigLookupentry entry = LLIST_TO_STRUCTP (llist_next (&item->lookup), lumiera_config_lookupentry, configitems); llist_unlink (&item->lookup); psplay_delete_node (&self->tree, (PSplaynode)entry); } else { /* more than this item present in hash, just unlink this item */ llist_unlink (&item->lookup); } return item; }
llist *quadtree_retrieve_node(quadtree *q, quadtree_node *qn, quadtree_rect *r, llist *list) { if (!qn) { return list; } if (qn->points && !llist_is_empty(qn->points)) { quadtree_data *d = llist_first(qn->points); if (quadtree_rect_contains(r, d->x, d->y)) { llist_append(list, qn->points); } } else { for(int i = 0; i < 4; i++) { if (quadtree_rect_contains_node(r, qn->children[i])) { quadtree_retrieve_node(q, qn->children[i], r, list); } } } return list; }
static int quadtree_insert_node(quadtree *q, quadtree_node *qn, void *data, size_t size, double x, double y) { if (!qn) { return QUADTREE_ERROR; } if (!quadtree_node_has_children(qn) && llist_is_empty(qn->points)) { quadtree_data *qd = quadtree_data_create(data, size, x, y); if (!qd) { return QUADTREE_ERROR; } llist_add_to_back(qn->points, qd, sizeof(quadtree_data)); free(qd); ++q->size; return QUADTREE_OK; } else { quadtree_data *d = llist_first(qn->points); if (d && quadtree_data_same_location(d, x, y)) { // Same point quadtree_data *qd = quadtree_data_create(data, size, x, y); if (!qd) { return QUADTREE_ERROR; } llist_add_to_back(qn->points, qd, sizeof(quadtree_data)); free(qd); return QUADTREE_OK; } else { quadtree_data *e = llist_first(qn->points); // Split node double minX = qn->bounds.x; double minY = qn->bounds.y; double midX = qn->bounds.x + qn->bounds.w / 2; double midY = qn->bounds.y + qn->bounds.h / 2; double maxX = qn->bounds.x + qn->bounds.w; double maxY = qn->bounds.y + qn->bounds.h; double xDim[4][2] = { { midX, maxX - midX }, { minX, midX - minX }, { minX, midX - minX }, { midX, maxX - midX } }; double yDim[4][2] = { { midY, maxY - midY }, { midY, maxY - midY }, { minY, midY - minY }, { minY, midY - minY } }; quadtree_data *d = llist_first(qn->points); int ret = QUADTREE_ERROR; for (int i = 0; i < 4; i++) { if (point_inside(xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1], x, y) || (d && point_inside(xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1], d->x, d->y))) { if (!qn->children[i]) { qn->children[i] = quadtree_node_create(); } quadtree_node_set_bounds(qn->children[i], xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1]); if (point_inside(xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1], x, y)) { quadtree_insert_node(q, qn->children[i], data, size, x, y); ret = QUADTREE_OK; } else if (point_inside(xDim[i][0], yDim[i][0], xDim[i][1], yDim[i][1], d->x, d->y)) { // Move contained points into child node qn->children[i]->points = qn->points; qn->points = NULL; ret = QUADTREE_OK; } } } return ret; } } // Shouldn't happen return QUADTREE_ERROR; }
END_TEST START_TEST ( llist_04_delete_nodes ) { int retval; //llist_node temp; llist listToTest = NULL; listToTest = llist_create ( NULL, trivial_equal, test_mt ? MT_SUPPORT_FALSE : MT_SUPPORT_TRUE ); // Insert a 5 nodes 1..5 retval = llist_add_node ( listToTest, ( llist_node ) 1, ADD_NODE_FRONT ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); retval = llist_add_node ( listToTest, ( llist_node ) 2, ADD_NODE_FRONT ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); retval = llist_add_node ( listToTest, ( llist_node ) 3, ADD_NODE_FRONT ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); retval = llist_add_node ( listToTest, ( llist_node ) 4, ADD_NODE_FRONT ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); retval = llist_add_node ( listToTest, ( llist_node ) 5, ADD_NODE_FRONT ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); printf ( "List after adding nodes: " ); print_llist ( listToTest ); // Delete tail retval = llist_delete_node ( listToTest, ( llist_node ) 1, false, NULL ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); printf ( "List after deleting tail: " ); print_llist ( listToTest ); // Delete node in the middle retval = llist_delete_node ( listToTest, ( llist_node ) 3, false, NULL ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); printf ( "List after deleting middle node: " ); print_llist ( listToTest ); // Delete head retval = llist_delete_node ( listToTest, ( llist_node ) 5, false, NULL ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); printf ( "List after deleting head node: " ); print_llist ( listToTest ); // Delete a node that doesn't exist retval = llist_delete_node ( listToTest, ( llist_node ) 6, false, NULL ); ck_assert_int_eq ( retval, LLIST_NODE_NOT_FOUND ); retval = llist_delete_node ( listToTest, ( llist_node ) 2, false, NULL ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); // The list should not be empty now ck_assert_int_eq(llist_is_empty ( listToTest ), FALSE ); ck_assert_int_eq(llist_is_empty ( listToTest ), FALSE ); // Delete last node retval = llist_delete_node ( listToTest, ( llist_node ) 4, false, NULL ); ck_assert_int_eq ( retval, LLIST_SUCCESS ); // The list should be empty now ck_assert_int_eq(llist_is_empty ( listToTest ), TRUE ); llist_destroy ( listToTest, false, NULL ); }