static void * critbit_delete_inplace(critbit_root *root, const char *key, int keylen) { if(!root->head) return NULL; const uint8_t *bytes = (void *)key; uint8_t *p = root->head; void **wherep = &root->head, **whereq = 0; critbit_node *q = NULL; int dir = 0; while(IS_INTERNAL(p)) { whereq = wherep; q = TO_NODE(p); dir = get_direction(q, bytes, keylen); wherep = q->child + dir; p = *wherep; } if(strcmp(key, (const char *)p) != 0) { return NULL; } if(!whereq) { root->head = NULL; return p; } *whereq = q->child[1 - dir]; __sync_synchronize(); return FROM_NODE(q); }
int critbit_delete(critbit_root *root, const char *key) { const size_t len = strlen(key); // begin critical section pthread_mutex_lock(&root->wlock); void * p = critbit_delete_inplace(root, key, len); pthread_rwlock_t *lock = root->cur_rwlock; pthread_rwlock_t *newlock = root->prev_rwlock; // swap two locks if(!__sync_val_compare_and_swap(&root->cur_rwlock, lock, newlock)) { printf("!!!\n"); } if(!__sync_val_compare_and_swap(&root->prev_rwlock, newlock, lock)) { printf("!!!\n"); } // wait until all readers are out pthread_rwlock_wrlock(lock); pthread_rwlock_unlock(lock); // end critical section pthread_mutex_unlock(&root->wlock); if(!p) return 1; if(!IS_INTERNAL(p)) { free_string(p); } else { critbit_node *node = TO_NODE(p); if(!IS_INTERNAL(node->child[0]) && strcmp(key, (const char *)node->child[0]) == 0) { free_string(node->child[0]); free_node(root, node); } else { free_string(node->child[1]); free_node(root, node); } } return 0; }
static void clear_node(void *p) { if(IS_INTERNAL(p)) { // Internal node critbit_node *node = TO_NODE(p); clear_node(node->child[0]); clear_node(node->child[1]); free(node); } else { free_string(p); } }
const critbit__extnode_t *critbit__lookup(const critbit__node_t *n, const void *key, size_t keylen) { const unsigned char *ukey = key; const unsigned char *ukeyend = ukey + keylen; int dir; for (; IS_INTERNAL(n); n = n->child[dir]) dir = GET_DIR(ukey, ukeyend, n->byte, n->otherbits); return FROM_STORE(n); }
/* {{{ proto AMQPExchange::setFlags(long bitmask) Set the exchange parameters */ static PHP_METHOD(amqp_exchange_class, setFlags) { PHP5to7_param_long_type_t flagBitmask; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &flagBitmask) == FAILURE) { return; } /* Set the flags based on the bitmask we were given */ flagBitmask = flagBitmask ? flagBitmask & PHP_AMQP_EXCHANGE_FLAGS : flagBitmask; zend_update_property_bool(this_ce, getThis(), ZEND_STRL("passive"), IS_PASSIVE(flagBitmask) TSRMLS_CC); zend_update_property_bool(this_ce, getThis(), ZEND_STRL("durable"), IS_DURABLE(flagBitmask) TSRMLS_CC); zend_update_property_bool(this_ce, getThis(), ZEND_STRL("auto_delete"), IS_AUTODELETE(flagBitmask) TSRMLS_CC); zend_update_property_bool(this_ce, getThis(), ZEND_STRL("internal"), IS_INTERNAL(flagBitmask) TSRMLS_CC); }
static int critbit_insert_inplace(critbit_root *root, const char *key, int keylen, const void* value) { const uint8_t *bytes = (void *)key; uint8_t *p = root->head; if(!p) { p = alloc_string(key, keylen, value); if(!p) return 1; root->head = p; return 0; } p = find_nearest(root->head, bytes, keylen); uint32_t newbyte; uint8_t newotherbits; for(newbyte = 0; newbyte < keylen; ++newbyte) { if(p[newbyte] != bytes[newbyte]) { newotherbits = p[newbyte] ^ bytes[newbyte]; goto found; } } if(p[newbyte]) { newotherbits = p[newbyte]; goto found; } return 1; found: while(newotherbits & (newotherbits - 1)) { newotherbits &= newotherbits - 1; } newotherbits ^= 0xFF; uint8_t c = p[newbyte]; int newdirection = (1 + (newotherbits | c)) >> 8; struct critbit_node *node = alloc_aligned(sizeof(struct critbit_node)); if(!node) return 1; char *x = alloc_string(key, keylen, value); if(!x) { free(node); return 1; } node->byte = newbyte; node->otherbits = newotherbits; node->child[1 - newdirection] = x; void **wherep = &root->head; for(;;) { uint8_t *p = *wherep; if(!IS_INTERNAL(p)) break; struct critbit_node *q = TO_NODE(p); if(q->byte > newbyte) break; if(q->byte == newbyte && q->otherbits > newotherbits) break; wherep = q->child + get_direction(q, bytes, keylen); } node->child[newdirection] = *wherep; __sync_synchronize(); *wherep = FROM_NODE(node); __sync_synchronize(); return 0; }