From: Ralph Ronnquist Date: Fri, 1 Jul 2022 11:07:50 +0000 (+1000) Subject: added auto-reclaim of zero indexes X-Git-Tag: 0.2~1 X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=f9a90dad5d64b519557f6774ed16c6e99b82f72a;p=rrq%2Frrqmisc.git added auto-reclaim of zero indexes --- diff --git a/tests/vectortests.c b/tests/vectortests.c index f85f7cc..6f8cdbd 100644 --- a/tests/vectortests.c +++ b/tests/vectortests.c @@ -6,12 +6,7 @@ #include #include -static int LINE; - -#define max(a,b) ((a>b)?a:b) -#define OUT(...) { \ - fprintf( stderr, __VA_ARGS__ ); \ -} +#define OUT(...) fprintf( stderr, __VA_ARGS__ ) // dump an item; return 0 to stop static void itemdump(const vector_index index,const void *slot) { diff --git a/vector/vector.c b/vector/vector.c index 6f44a64..2f1010c 100644 --- a/vector/vector.c +++ b/vector/vector.c @@ -143,7 +143,7 @@ static unsigned long VECTOR_INDEX_PART_DEC( #define ONES (~((vector_index) 0)) -// Set index to last value for all index parts at level and lower. +// Set index to first value for all index parts at level and lower. static void VECTOR_INDEX_FIRST(vector *pv,vector_index *index, int level) { (*index) &= ONES << ( VECTOR_BITS[ pv->variant ] * level ); } @@ -194,26 +194,38 @@ static unsigned int vector_levels(vector *pv,unsigned int size) { * update the index slots accordingly. The given index is advanced * cyclically to match the found slot. The function returns a slot * pointer to the used slot, if any, and 0 otherwise. + * The last parameter is a flag that gets set when the scanning is + * partial (i.e. not the whole index page). */ static void **vector_level_next_used( vector *pv, vector_page *page, vector_index *index, int level, - vector_index end ) + int *partial ) { void **p = (void**)&(*page)[ VECTOR_INDEX_PART( pv, index, level ) ]; - for( ; *index < end; p++ ) { + if ( VECTOR_INDEX_PART( pv, index, level ) != 0 ) { + *partial = 1; + } + for( ; *index < pv->size; p++ ) { if ( *p ) { if ( level == 0 ) { return p; // This is a used entry } // *p is an index that needs to be inspected recursively - void **x = vector_level_next_used( pv, *p, index, level - 1, end ); + int w = 0; + void **x = vector_level_next_used( pv, *p, index, level - 1, &w ); if ( x ) { return x; // Used slot was found; return it. } // If the page *p is all empty, so can/should be reclaimed. + if ( w == 0 ) { + free( *p ); + *p = 0; + } else { + *partial = 1; + } } else { if ( level > 0 ) { VECTOR_INDEX_FIRST( pv, index, level - 1 ); @@ -235,20 +247,25 @@ void **vector_next_used(vector *pv,vector_index *index) { return 0; } int levels = vector_levels( pv, pv->size ); - for ( ; *index < pv->size; (*index)++ ) { + int partial = 0; + do { void **slot = vector_level_next_used( - pv, pv->entries, index, levels - 1, pv->size ) ; + pv, pv->entries, index, levels - 1, &partial ) ; if ( slot == 0 ) { - *index = pv->size; // reached the end of the vector - } else if ( *slot == 0 ) { - continue; + break; // reached the end of the vector + } + if ( *slot ) { + return slot; } - return slot; + } while ( ++(*index) < pv->size ); + if ( partial == 0 ) { + free( pv->entries ); + pv->entries = 0; } + *index = pv->size; // reached the end of the vector return 0; } -#if 1 /** * Advances a vector index to the prior used slot at or below the * given level, starting from the indexed entry (inclusive) and down. @@ -256,25 +273,38 @@ void **vector_next_used(vector *pv,vector_index *index) { * update the index slots accordingly. The given index is advanced * cyclically to match the found slot. The function returns a slot * pointer to the used slot, if any, and 0 otherwise. + * The last parameter is a flag that gets set when the scanning is + * partial (i.e. not the whole index page). */ static void **vector_level_prev_used( vector *pv, vector_page *page, vector_index *index, - int level ) + int level, + int *partial ) { void **p = (void**)&(*page)[ VECTOR_INDEX_PART( pv, index, level ) ]; + if ( VECTOR_INDEX_PART( pv, index, level ) != VECTOR_SLOTS( pv ) - 1 ) { + *partial = 1; + } do { if ( *p ) { if ( level == 0 ) { return p; // This is a used entry } // *p is an index that needs to be inspected recursively - void **x = vector_level_prev_used( pv, *p, index, level - 1 ); + int w = 0; + void **x = vector_level_prev_used( pv, *p, index, level - 1, &w ); if ( x ) { return x; // Used slot was found; return it. } - // If the page *p is all empty, so can/should be reclaimed. + // If the page *p is all empty, it can/should be reclaimed. + if ( w == 0 ) { + free( *p ); + *p = 0; + } else { + *partial = 1; + } } else { if ( level > 0 ) { VECTOR_INDEX_LAST( pv, index, level ); @@ -294,9 +324,10 @@ void **vector_prev_used(vector *pv,vector_index *index) { return 0; } int levels = vector_levels( pv, pv->size ); + int partial = 0; do { void **slot = vector_level_prev_used( - pv, pv->entries, index, levels - 1 ) ; + pv, pv->entries, index, levels - 1, &partial ) ; if ( slot == 0 ) { break; // reached the end of the vector } @@ -304,49 +335,14 @@ void **vector_prev_used(vector *pv,vector_index *index) { return slot; } } while ( (*index)-- != 0 ); - *index = pv->size; - return 0; -} - -#endif - -#if 0 -// Find the first in-use slot at or before the index, at the level -static void **vector_prev_used_level(vector *pv,vector_index *index,int lv) { - void **slot = vector_access( pv, *index, lv, 0 ); - if ( slot == 0 ) { - return 0; + if ( partial == 0 ) { + free( pv->entries ); + pv->entries = 0; } - do { - if ( *slot ) { - if ( lv == 0 ) { - return slot; - } - void **sub = vector_prev_used_level( pv, index, lv - 1 ); - if ( sub ) { - return sub; - } - } - slot--; - } while ( VECTOR_INDEX_PART_DEC( pv, index, lv ) != 0 ); + *index = pv->size; // reached the end of the vector return 0; } -// Find nearest used slot at or prior to the given index. -void **vector_prev_used(vector *pv,vector_index *index) { - if ( pv->entries == 0 || *index >= pv->size ) { - *index = pv->size; - return 0; - } - void **slot = vector_prev_used_level( - pv, index, vector_levels( pv, pv->size ) - 1 ); - if ( slot == 0 ) { - *index = pv->size; - } - return slot; -} -#endif - // Reclaim tree of unused pages for a given level static void vector_reclaim(vector *pv,vector_page *page,unsigned int level) { int i = 0; @@ -615,7 +611,7 @@ void vector_iterate(vector *pv, int i = index & ( end - 1 ); for ( ; i < end && index < pv->size; i++, index++ ) { void **slot = vector_access( pv, index, 0, 0 ); - if ( slot && itemfn( index, *slot, data ) ) { + if ( itemfn( index, slot? *slot: 0, data ) ) { return; } }