Skip to content

Commit

Permalink
chore(rax_tree): Introduce raxFreeWithCallback call in RaxTreeMap des…
Browse files Browse the repository at this point in the history
…tructor

Signed-off-by: Stepan Bagritsevich <[email protected]>
  • Loading branch information
BagritsevichStepan committed Dec 4, 2024
1 parent e7d762e commit c292bfe
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 12 deletions.
16 changes: 10 additions & 6 deletions src/core/search/rax_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,16 @@ template <typename V> struct RaxTreeMap {
}

~RaxTreeMap() {
for (auto it = begin(); it != end(); ++it) {
V* ptr = &(*it).second;
std::allocator_traits<decltype(alloc_)>::destroy(alloc_, ptr);
alloc_.deallocate(ptr, 1);
}
raxFree(tree_);
using Allocator = decltype(alloc_);

auto free_callback = [](void* data, void* context) {
Allocator* allocator = static_cast<Allocator*>(context);
V* ptr = static_cast<V*>(data);
std::allocator_traits<Allocator>::destroy(*allocator, ptr);
allocator->deallocate(ptr, 1);
};

raxFreeWithCallbackAndArgument(tree_, free_callback, &alloc_);
}

size_t size() const {
Expand Down
27 changes: 21 additions & 6 deletions src/redis/rax.c
Original file line number Diff line number Diff line change
Expand Up @@ -1221,29 +1221,44 @@ int raxRemove(rax *rax, unsigned char *s, size_t len, void **old) {

/* This is the core of raxFree(): performs a depth-first scan of the
* tree and releases all the nodes found. */
void raxRecursiveFree(rax *rax, raxNode *n, void (*free_callback)(void*)) {
void raxRecursiveFree(rax *rax, raxNode *n, void (*free_callback)(void*, void*), void* argument) {
debugnode("free traversing",n);
int numchildren = n->iscompr ? 1 : n->size;
raxNode **cp = raxNodeLastChildPtr(n);
while(numchildren--) {
raxNode *child;
memcpy(&child,cp,sizeof(child));
raxRecursiveFree(rax,child,free_callback);
raxRecursiveFree(rax,child,free_callback,argument);
cp--;
}
debugnode("free depth-first",n);
if (free_callback && n->iskey && !n->isnull)
free_callback(raxGetData(n));
free_callback(raxGetData(n),argument);
rax_free(n);
rax->numnodes--;
}

/* Free the entire radix tree, invoking a free_callback function for each key's data.
* An additional argument is passed to the free_callback function.*/
void raxFreeWithCallbackAndArgument(rax *rax, void (*free_callback)(void*, void*), void* argument) {
raxRecursiveFree(rax,rax->head,free_callback,argument);
assert(rax->numnodes == 0);
rax_free(rax);
}

/* Wrapper for the callback to adapt it for the context */
void freeCallbackWrapper(void* data, void* argument) {
if (!argument) {
return;
}
void (*free_callback)(void*) = (void (*)(void*))argument;
free_callback(data);
}

/* Free a whole radix tree, calling the specified callback in order to
* free the auxiliary data. */
void raxFreeWithCallback(rax *rax, void (*free_callback)(void*)) {
raxRecursiveFree(rax,rax->head,free_callback);
assert(rax->numnodes == 0);
rax_free(rax);
raxFreeWithCallbackAndArgument(rax, freeCallbackWrapper, (void*)free_callback);
}

/* Free a whole radix tree. */
Expand Down
1 change: 1 addition & 0 deletions src/redis/rax.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ int raxRemove(rax *rax, unsigned char *s, size_t len, void **old);
void *raxFind(rax *rax, unsigned char *s, size_t len);
void raxFree(rax *rax);
void raxFreeWithCallback(rax *rax, void (*free_callback)(void*));
void raxFreeWithCallbackAndArgument(rax *rax, void (*free_callback)(void*, void*), void* argument);
void raxStart(raxIterator *it, rax *rt);
int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len);
int raxNext(raxIterator *it);
Expand Down

0 comments on commit c292bfe

Please sign in to comment.