[ccan] [PATCH] btree: Add custom allocator interface.
Rusty Russell
rusty at rustcorp.com.au
Mon Feb 8 11:45:32 AEDT 2016
stuartl at longlandclan.id.au writes:
> From: Stuart Longland <me at vk4msl.id.au>
>
> This provides a way for btree to be used with external allocator
> libraries such as the tal or talloc modules.
Sure. In my libraries I generally use a global allocator override;
it's not thread-safe, but much easier to use in practice.
Since I don't use btree, I'm agnostic about it though!
Minor nits below:
> ---
> ccan/btree/btree.c | 194 +++++++++++++++++++++++++++++++----------------------
> ccan/btree/btree.h | 29 +++++---
> 2 files changed, 136 insertions(+), 87 deletions(-)
>
> diff --git a/ccan/btree/btree.c b/ccan/btree/btree.c
> index 636edbc..5bb2435 100644
> --- a/ccan/btree/btree.c
> +++ b/ccan/btree/btree.c
> @@ -29,12 +29,15 @@
> #define MAX (BTREE_ITEM_MAX)
> #define MIN (BTREE_ITEM_MAX >> 1)
>
> -static struct btree_node *node_alloc(int internal);
> +static struct btree_node *node_alloc(const struct btree_allocator* alloc, int internal);
> static void node_delete(struct btree_node *node, struct btree *btree);
> +static void node_free(struct btree_node *node);
>
> static void branch_begin(btree_iterator iter);
> static void branch_end(btree_iterator iter);
> static void begin_end_lr(btree_iterator iter, struct btree_node *node, int lr);
> +static void* default_malloc(const struct btree_allocator* alloc, size_t size);
> +static void default_free(const struct btree_allocator* alloc, void* ptr);
You don't need to pre-declare these, see below.
> /*
> * If iter->node has parent, returns 1 and ascends the iterator such that
> @@ -65,11 +68,19 @@ static int node_walk_forward(const struct btree_node *node,
>
> struct btree *btree_new(btree_search_t search)
> {
> - struct btree *btree = calloc(1, sizeof(struct btree));
> - struct btree_node *node = node_alloc(0);
> + return btree_new_with_alloc(search, &BTREE_DEFAULT_ALLOCATOR);
> +}
> +
> +struct btree *btree_new_with_alloc(btree_search_t search,
> + const struct btree_allocator *alloc)
> +{
> + struct btree *btree = (*(alloc->malloc))(alloc, sizeof(struct btree));
You can call a function pointer, so alloc->malloc(alloc, sizeof(struct btree));
should work.
> + struct btree_node *node = node_alloc(alloc, 0);
> node->parent = NULL;
> node->count = 0;
> node->depth = 0;
> + memset(btree, 0, sizeof(struct btree));
> + btree->alloc = alloc;
> btree->root = node;
> btree->search = search;
> btree->multi = false;
> @@ -79,16 +90,16 @@ struct btree *btree_new(btree_search_t search)
> void btree_delete(struct btree *btree)
> {
> node_delete(btree->root, btree);
> - free(btree);
> + (*(btree->alloc->free))(btree->alloc, btree);
> }
Ditto.
> bool btree_insert(struct btree *btree, const void *item)
> {
> btree_iterator iter;
> -
> +
> if (btree_find_last(btree, item, iter) && !btree->multi)
> return false;
> -
> +
Lots of whitespace cleanups. Not a problem, but prefer a separate patch
for clarity.
> +
> +/* Default allocator implementation */
> +const struct btree_allocator BTREE_DEFAULT_ALLOCATOR = {
> + .malloc = default_malloc,
> + .free = default_free,
> +};
> +
> +static void* default_malloc(const struct btree_allocator* alloc, size_t size)
> +{
> + return malloc(size);
> +}
> +
> +static void default_free(const struct btree_allocator* alloc, void* ptr)
> +{
> + free(ptr);
> +}
Put default_malloc and default_free above the BTREE_DEFAULT_ALLOCATOR
definition, and you don't need to pre-declare them.
Thanks,
Rusty.
More information about the ccan
mailing list