diff options
author | sasha@mysql.sashanet.com <> | 2001-05-12 19:50:51 -0600 |
---|---|---|
committer | sasha@mysql.sashanet.com <> | 2001-05-12 19:50:51 -0600 |
commit | ef27ec42c2a6b361e7c158bc5974ea3dd5301804 (patch) | |
tree | 9a5be3c1de61f22213e62a51418e4cb6820cdc33 /mysys | |
parent | b2977103af66508bf5697a2fe778c94293408338 (diff) | |
download | mariadb-git-ef27ec42c2a6b361e7c158bc5974ea3dd5301804.tar.gz |
option to free_root() to not my_free() the blocks
fixed bug/updated count_distinct2 test
changed reset in count distinct to avoid calls to my_free()
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/my_alloc.c | 41 | ||||
-rw-r--r-- | mysys/tree.c | 18 |
2 files changed, 55 insertions, 4 deletions
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index db482454e69..b82ff965dfb 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -100,7 +100,41 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) #endif } - /* deallocate everything used by alloc_root */ +static inline void mark_blocks_free(MEM_ROOT* root) +{ + reg1 USED_MEM *next,*last = 0; + + /* iterate through (partially) free blocks, mark them fully free */ + for(next = root->free; next; next = next->next ) + { + last = next; + next->left = next->size - ALIGN_SIZE(sizeof(USED_MEM)); + } + /* if free block list was not empty, point the next of the + last free block to the beginning of the used list */ + next = root->used; /* a little optimization to avoid dereferencing root + twice - we will shortly start iterating through used + list */ + if(last) + last->next = next; + else /* if free list is empty, just point it to the current used*/ + root->free = next; + + /* now go through the current used list, and mark each block + as fully free. Note that because of our optimization, we do not + need to initialize next here - see above + */ + for(;next; next = next->next) + next->left = next->size - ALIGN_SIZE(sizeof(USED_MEM)); + + /* Now everything is set - we just need to indicate that nothing is used + anymore + */ + root->used = 0; +} + + /* deallocate everything used by alloc_root or just move + used blocks to free list if called with MY_USED_TO_FREE */ void free_root(MEM_ROOT *root, myf MyFlags) { @@ -109,6 +143,11 @@ void free_root(MEM_ROOT *root, myf MyFlags) if (!root) DBUG_VOID_RETURN; /* purecov: inspected */ + if(MyFlags & MY_MARK_BLOCKS_FREE) + { + mark_blocks_free(root); + DBUG_VOID_RETURN; + } if (!(MyFlags & MY_KEEP_PREALLOC)) root->pre_alloc=0; diff --git a/mysys/tree.c b/mysys/tree.c index e46ff00adad..af64be55d2f 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -103,9 +103,9 @@ void init_tree(TREE *tree, uint default_alloc_size, int size, DBUG_VOID_RETURN; } -void delete_tree(TREE *tree) +static void free_tree(TREE *tree, myf free_flags) { - DBUG_ENTER("delete_tree"); + DBUG_ENTER("free_tree"); DBUG_PRINT("enter",("tree: %lx",tree)); if (tree->root) /* If initialized */ @@ -116,7 +116,7 @@ void delete_tree(TREE *tree) { if (tree->free) delete_tree_element(tree,tree->root); - free_root(&tree->mem_root,MYF(0)); + free_root(&tree->mem_root, free_flags); } } tree->root= &tree->null_element; @@ -125,6 +125,18 @@ void delete_tree(TREE *tree) DBUG_VOID_RETURN; } +void delete_tree(TREE* tree) +{ + free_tree(tree, MYF(0)); /* my_free() mem_root if applicable */ +} + +void reset_tree(TREE* tree) +{ + free_tree(tree, MYF(MY_MARK_BLOCKS_FREE)); + /* do not my_free() mem_root if applicable, just mark blocks as free */ +} + + static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) { if (element != &tree->null_element) |