mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 01:12:13 +00:00
Add immortal string block allocator
[SVN r14301]
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
# include "jam.h"
|
||||
# include "newstr.h"
|
||||
# include "hash.h"
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
/*
|
||||
* newstr.c - string manipulation routines
|
||||
@@ -33,6 +35,61 @@ typedef char *STRING;
|
||||
static struct hash *strhash = 0;
|
||||
static int strtotal = 0;
|
||||
|
||||
/*
|
||||
* Immortal string allocator implementation speeds string allocation
|
||||
* and cuts down on internal fragmentation
|
||||
*/
|
||||
|
||||
# define STRING_BLOCK 4096
|
||||
typedef struct strblock
|
||||
{
|
||||
struct strblock* next;
|
||||
char data[STRING_BLOCK];
|
||||
} strblock;
|
||||
|
||||
static strblock* strblock_chain = 0;
|
||||
|
||||
/* Storage remaining in the current strblock */
|
||||
static char* storage_start = 0;
|
||||
static char* storage_finish = 0;
|
||||
|
||||
/*
|
||||
* allocate() - Allocate n bytes of immortal string storage
|
||||
*/
|
||||
static char* allocate(size_t n)
|
||||
{
|
||||
/* See if we can grab storage from an existing block */
|
||||
size_t remaining = storage_finish - storage_start;
|
||||
if ( remaining >= n )
|
||||
{
|
||||
char* result = storage_start;
|
||||
storage_start += n;
|
||||
return result;
|
||||
}
|
||||
else /* Must allocate a new block */
|
||||
{
|
||||
strblock* new_block;
|
||||
size_t nalloc = n;
|
||||
if ( nalloc < STRING_BLOCK )
|
||||
nalloc = STRING_BLOCK;
|
||||
|
||||
/* allocate a new block and link into the chain */
|
||||
new_block = malloc( offsetof( strblock, data[nalloc] ) );
|
||||
if ( new_block == 0 )
|
||||
return 0;
|
||||
new_block->next = strblock_chain;
|
||||
strblock_chain = new_block;
|
||||
|
||||
/* Take future allocations out of the larger remaining space */
|
||||
if ( remaining < nalloc - n )
|
||||
{
|
||||
storage_start = new_block->data + n;
|
||||
storage_finish = new_block->data + nalloc;
|
||||
}
|
||||
return new_block->data;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* newstr() - return a malloc'ed copy of a string
|
||||
*/
|
||||
@@ -50,7 +107,7 @@ newstr( char *string )
|
||||
if( hashenter( strhash, (HASHDATA **)&s ) )
|
||||
{
|
||||
int l = strlen( string );
|
||||
char *m = (char *)malloc( l + 1 );
|
||||
char *m = (char *)allocate( l + 1 );
|
||||
|
||||
strtotal += l + 1;
|
||||
memcpy( m, string, l + 1 );
|
||||
@@ -86,8 +143,16 @@ freestr( char *s )
|
||||
void
|
||||
donestr()
|
||||
{
|
||||
hashdone( strhash );
|
||||
|
||||
if( DEBUG_MEM )
|
||||
printf( "%dK in strings\n", strtotal / 1024 );
|
||||
/* Reclaim string blocks */
|
||||
while ( strblock_chain != 0 )
|
||||
{
|
||||
strblock* n = strblock_chain->next;
|
||||
free(strblock_chain);
|
||||
strblock_chain = n;
|
||||
}
|
||||
|
||||
hashdone( strhash );
|
||||
|
||||
if( DEBUG_MEM )
|
||||
printf( "%dK in strings\n", strtotal / 1024 );
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
# include "jam.h"
|
||||
# include "newstr.h"
|
||||
# include "hash.h"
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
/*
|
||||
* newstr.c - string manipulation routines
|
||||
@@ -33,6 +35,61 @@ typedef char *STRING;
|
||||
static struct hash *strhash = 0;
|
||||
static int strtotal = 0;
|
||||
|
||||
/*
|
||||
* Immortal string allocator implementation speeds string allocation
|
||||
* and cuts down on internal fragmentation
|
||||
*/
|
||||
|
||||
# define STRING_BLOCK 4096
|
||||
typedef struct strblock
|
||||
{
|
||||
struct strblock* next;
|
||||
char data[STRING_BLOCK];
|
||||
} strblock;
|
||||
|
||||
static strblock* strblock_chain = 0;
|
||||
|
||||
/* Storage remaining in the current strblock */
|
||||
static char* storage_start = 0;
|
||||
static char* storage_finish = 0;
|
||||
|
||||
/*
|
||||
* allocate() - Allocate n bytes of immortal string storage
|
||||
*/
|
||||
static char* allocate(size_t n)
|
||||
{
|
||||
/* See if we can grab storage from an existing block */
|
||||
size_t remaining = storage_finish - storage_start;
|
||||
if ( remaining >= n )
|
||||
{
|
||||
char* result = storage_start;
|
||||
storage_start += n;
|
||||
return result;
|
||||
}
|
||||
else /* Must allocate a new block */
|
||||
{
|
||||
strblock* new_block;
|
||||
size_t nalloc = n;
|
||||
if ( nalloc < STRING_BLOCK )
|
||||
nalloc = STRING_BLOCK;
|
||||
|
||||
/* allocate a new block and link into the chain */
|
||||
new_block = malloc( offsetof( strblock, data[nalloc] ) );
|
||||
if ( new_block == 0 )
|
||||
return 0;
|
||||
new_block->next = strblock_chain;
|
||||
strblock_chain = new_block;
|
||||
|
||||
/* Take future allocations out of the larger remaining space */
|
||||
if ( remaining < nalloc - n )
|
||||
{
|
||||
storage_start = new_block->data + n;
|
||||
storage_finish = new_block->data + nalloc;
|
||||
}
|
||||
return new_block->data;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* newstr() - return a malloc'ed copy of a string
|
||||
*/
|
||||
@@ -50,7 +107,7 @@ newstr( char *string )
|
||||
if( hashenter( strhash, (HASHDATA **)&s ) )
|
||||
{
|
||||
int l = strlen( string );
|
||||
char *m = (char *)malloc( l + 1 );
|
||||
char *m = (char *)allocate( l + 1 );
|
||||
|
||||
strtotal += l + 1;
|
||||
memcpy( m, string, l + 1 );
|
||||
@@ -86,8 +143,16 @@ freestr( char *s )
|
||||
void
|
||||
donestr()
|
||||
{
|
||||
hashdone( strhash );
|
||||
|
||||
if( DEBUG_MEM )
|
||||
printf( "%dK in strings\n", strtotal / 1024 );
|
||||
/* Reclaim string blocks */
|
||||
while ( strblock_chain != 0 )
|
||||
{
|
||||
strblock* n = strblock_chain->next;
|
||||
free(strblock_chain);
|
||||
strblock_chain = n;
|
||||
}
|
||||
|
||||
hashdone( strhash );
|
||||
|
||||
if( DEBUG_MEM )
|
||||
printf( "%dK in strings\n", strtotal / 1024 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user