/* verify that all API calls are exported */ static void test_api(void) { CRBTree t = {}; CRBNode n = C_RBNODE_INIT(n); assert(!c_rbnode_is_linked(&n)); /* init, is_linked, add, remove, remove_init */ c_rbtree_add(&t, NULL, &t.root, &n); assert(c_rbnode_is_linked(&n)); c_rbtree_remove_init(&t, &n); assert(!c_rbnode_is_linked(&n)); c_rbtree_add(&t, NULL, &t.root, &n); assert(c_rbnode_is_linked(&n)); c_rbtree_remove(&t, &n); assert(c_rbnode_is_linked(&n)); /* @n wasn't touched */ c_rbnode_init(&n); assert(!c_rbnode_is_linked(&n)); /* first, last, leftmost, rightmost, next, prev */ assert(!c_rbtree_first(&t)); assert(!c_rbtree_last(&t)); assert(&n == c_rbnode_leftmost(&n)); assert(&n == c_rbnode_rightmost(&n)); assert(!c_rbnode_next(&n)); assert(!c_rbnode_prev(&n)); }
/** * b1_node_implement() - implement interface on node * @node: node to operate on * @interface: interface to implement * * Extend @node to support the interface given as @interface. From then on, the * node will dispatch incoming method calls on this interface. * * This fails, if the given interface is already implemented by @node. * * Return: 0 on success, negative error code on failure. */ _c_public_ int b1_node_implement(B1Node *node, B1Interface *interface) { B1Implementation *implementation; CRBNode **slot, *p; assert(node); assert(interface); if (node->live || node->slot) return -EBUSY; slot = c_rbtree_find_slot(&node->implementations, implementations_compare, interface->name, &p); if (!slot) return -ENOTUNIQ; implementation = calloc(1, sizeof(*implementation)); if (!implementation) return -ENOMEM; c_rbnode_init(&implementation->rb); implementation->interface = b1_interface_ref(interface); interface->implemented = true; c_rbtree_add(&node->implementations, p, slot, &implementation->rb); return 0; }
int b1_handle_acquire(B1Handle **handlep, B1Peer *peer, uint64_t handle_id) { B1Handle *handle; CRBNode **slot, *p; int r; assert(handlep); assert(peer); if (handle_id == BUS1_HANDLE_INVALID) { *handlep = NULL; return 0; } slot = c_rbtree_find_slot(&peer->handles, handles_compare, &handle_id, &p); if (slot) { r = b1_handle_new(peer, handle_id, &handle); if (r < 0) return r; c_rbtree_add(&peer->handles, p, slot, &handle->rb); } else { handle = c_container_of(p, B1Handle, rb); b1_handle_ref(handle); b1_handle_release(handle); } *handlep = handle; return 0; }
static void test_child1(TestContext *ctx) { CRBNode *p, **slot; size_t i; for (i = 0; i < ctx->n_nodes; ++i) { child_assert(!c_rbnode_is_linked(ctx->nodes[i])); slot = c_rbtree_find_slot(ctx->tree, compare, ctx->nodes[i], &p); c_rbtree_add(ctx->tree, p, slot, ctx->nodes[i]); } }
/* run tests against the c_rbtree_find*() helpers */ static void test_map(void) { CRBNode **slot, *p; CRBTree t = {}; Node *nodes[2048]; unsigned long i; /* allocate and initialize all nodes */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { nodes[i] = malloc(sizeof(*nodes[i])); assert(nodes[i]); nodes[i]->key = i; c_rbnode_init(&nodes[i]->rb); } /* shuffle nodes */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); /* add all nodes, and verify that each node is linked */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { assert(!c_rbnode_is_linked(&nodes[i]->rb)); assert(!c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb)); slot = c_rbtree_find_slot(&t, compare, (void *)nodes[i]->key, &p); assert(slot); c_rbtree_add(&t, p, slot, &nodes[i]->rb); assert(c_rbnode_is_linked(&nodes[i]->rb)); assert(nodes[i] == c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb)); } /* shuffle nodes again */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); /* remove all nodes (in different order) */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { assert(c_rbnode_is_linked(&nodes[i]->rb)); assert(nodes[i] == c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb)); c_rbtree_remove_init(&t, &nodes[i]->rb); assert(!c_rbnode_is_linked(&nodes[i]->rb)); assert(!c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb)); } /* free nodes again */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) free(nodes[i]); }
int b1_handle_link(B1Handle *handle) { CRBNode **slot, *p; assert(handle); assert(handle->id != BUS1_HANDLE_INVALID); assert(handle->holder); slot = c_rbtree_find_slot(&handle->holder->handles, handles_compare, &handle->id, &p); if (!slot) return -ENOTUNIQ; c_rbtree_add(&handle->holder->handles, p, slot, &handle->rb); return 0; }
int b1_node_link(B1Node *node) { CRBNode **slot, *p; assert(node); assert(node->id != BUS1_HANDLE_INVALID); assert(node->owner); slot = c_rbtree_find_slot(&node->owner->nodes, nodes_compare, &node->id, &p); if (!slot) return -ENOTUNIQ; c_rbtree_add(&node->owner->nodes, p, slot, &node->rb); return 0; }
int b1_handle_acquire(B1Peer *peer, B1Handle **handlep, uint64_t handle_id) { B1Handle *handle; CRBNode **slot, *p; int r; assert(peer); assert(handlep); if (handle_id == BUS1_HANDLE_INVALID) { *handlep = NULL; return 0; } slot = c_rbtree_find_slot(&peer->handles, handles_compare, &handle_id, &p); if (slot) { r = b1_handle_new(peer, &handle); if (r < 0) return r; handle->ref_kernel = (CRef)C_REF_INIT; handle->live = true; handle->id = handle_id; c_rbtree_add(&peer->handles, p, slot, &handle->rb); } else { handle = c_container_of(p, B1Handle, rb); if (handle->live) { c_ref_inc(&handle->ref_kernel); /* reusing existing handle, drop redundant reference from kernel */ r = bus1_peer_handle_release(handle->holder->peer, handle->id); if (r < 0) return r; } else { handle->ref_kernel = (CRef)C_REF_INIT; handle->live = true; } c_ref_inc(&handle->ref); } *handlep = handle; return 0; }
static void insert(CRBTree *t, CRBNode *n) { CRBNode **i, *p; assert(t); assert(n); assert(!c_rbnode_is_linked(n)); i = &t->root; p = NULL; while (*i) { p = *i; if (n < *i) { i = &(*i)->left; } else { assert(n > *i); i = &(*i)->right; } } c_rbtree_add(t, p, i, n); }