Skip to content

Commit

Permalink
Z_StringPool: Growing pool for immutable strings in zone memory
Browse files Browse the repository at this point in the history
  • Loading branch information
aufau committed Oct 19, 2024
1 parent 6426902 commit a50ec9f
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 52 deletions.
63 changes: 63 additions & 0 deletions src/qcommon/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,13 @@ int Z_Size(void *pvAddress)
return pMemory->iSize;
}

memtag_t Z_Tag(void *pvAddress)
{
zoneHeader_t *pMemory = ((zoneHeader_t *)pvAddress) - 1;

return pMemory->eTag;
}


// Frees a block of memory...
//
Expand Down Expand Up @@ -1368,6 +1375,62 @@ const char *CopyString( const char *in, memtag_t eTag ) {
return out;
}

/*
========================
StringPool
Growing pool for allocating immutable C strings in Zone Memory
that avoids too many allocations and fragmentation
========================
*/

typedef struct stringPool_s {
unsigned int size;
unsigned int tail;
struct stringPool_s *next;
char buffer[0];
} stringPool_t;

stringPool_t *Z_StringPoolNew(unsigned int size, memtag_t eTag) {
unsigned int size_ = PAD(size, 16);
stringPool_t *chunk = (stringPool_t *)Z_Malloc(offsetof(stringPool_t, buffer) + size_, eTag, qfalse);

chunk->size = size_;
chunk->tail = 0;
chunk->next = NULL;

return chunk;
}

void Z_StringPoolFree(stringPool_t * pool) {
stringPool_t *chunk = pool;

while (chunk) {
stringPool_t *nextChunk = chunk->next;
Z_Free(chunk);
chunk = nextChunk;
}
}

const char *Z_StringPoolAdd(stringPool_t * pool, const char * string) {
stringPool_t *chunk = pool;
unsigned int len = strlen(string) + 1;

while (chunk->size < chunk->tail + len) {
if (!chunk->next) {
unsigned int size = 2 * MAX(len, chunk->size);
memtag_t eTag = Z_Tag(chunk);
chunk->next = Z_StringPoolNew(size, eTag);
}

chunk = chunk->next;
}

memcpy(chunk->buffer + chunk->tail, string, len);
chunk->tail += len;

return chunk->buffer + chunk->tail - len;
}

/*
==============================================================================
Expand Down
58 changes: 6 additions & 52 deletions src/qcommon/files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,6 @@ typedef struct fileInPack_s {
struct fileInPack_s* next; // next file in the hash
} fileInPack_t;

typedef struct stringBuffer_s {
unsigned int size;
unsigned int tail;
struct stringBuffer_s *next;
char buffer[0];
} stringBuffer_t;

enum {
PACKGVC_UNKNOWN = 0,
PACKGVC_1_02 = 1,
Expand All @@ -222,7 +215,7 @@ typedef struct {
int hashSize; // hash table size (power of 2)
fileInPack_t* *hashTable; // hash table
fileInPack_t* buildBuffer; // buffer with the filenames etc.
stringBuffer_t* namesBuffer; // buffer with filenames
stringPool_t* namesBuffer; // buffer with filenames
int gvc; // game-version compatibility
qboolean isJKA; // jka assets
} pack_t;
Expand Down Expand Up @@ -333,45 +326,6 @@ static inline qboolean FS_CheckHandle(const char *fname, fileHandle_t f, module_

#define FS_CHECKHANDLE(f, module, retval) if (!FS_CheckHandle(__FUNCTION__, f, module)) return retval;

static stringBuffer_t *FS_NewStringBuffer(unsigned int size) {
unsigned int size_ = PAD(size, 16);
stringBuffer_t *buffer = (stringBuffer_t *)Z_Malloc(offsetof(stringBuffer_t, buffer) + size_, TAG_FILESYS, qfalse);

buffer->size = size_;
buffer->tail = 0;
buffer->next = NULL;

return buffer;
}

static void FS_FreeStringBuffer(stringBuffer_t * buffer) {
stringBuffer_t *chunk = buffer;

while (chunk) {
stringBuffer_t *nextChunk = chunk->next;
Z_Free(chunk);
chunk = nextChunk;
}
}

static const char *FS_AppendStringBuffer(stringBuffer_t * buffer, const char * string) {
stringBuffer_t *chunk = buffer;
unsigned int len = strlen(string) + 1;

while (chunk->size < chunk->tail + len) {
if (!chunk->next) {
chunk->next = FS_NewStringBuffer(2 * MAX(len, chunk->size));
}

chunk = chunk->next;
}

memcpy(chunk->buffer + chunk->tail, string, len);
chunk->tail += len;

return chunk->buffer + chunk->tail - len;
}

/*
==============
FS_Initialized
Expand Down Expand Up @@ -2007,7 +1961,7 @@ of a zip file.
static pack_t *FS_LoadZipFile( char *zipfile, const char *basename, qboolean assetsJKA )
{
fileInPack_t *buildBuffer;
stringBuffer_t *namesBuffer;
stringPool_t *namesBuffer;
pack_t *pack;
unzFile uf;
int err;
Expand All @@ -2031,7 +1985,7 @@ static pack_t *FS_LoadZipFile( char *zipfile, const char *basename, qboolean ass
fs_packFiles += gi.number_entry;

buildBuffer = (struct fileInPack_s *)Z_Malloc((int)((gi.number_entry * sizeof(fileInPack_t))), TAG_FILESYS, qtrue);
namesBuffer = FS_NewStringBuffer(gi.number_entry * 16);
namesBuffer = Z_StringPoolNew(gi.number_entry * 16, TAG_FILESYS);
fs_headerLongs = (int *)Z_Malloc( gi.number_entry * sizeof(int), TAG_FILESYS, qtrue );

// get the hash table size from the number of files in the zip
Expand Down Expand Up @@ -2083,7 +2037,7 @@ static pack_t *FS_LoadZipFile( char *zipfile, const char *basename, qboolean ass
}
Q_strlwr( filename_inzip );
hash = FS_HashFileName(filename_inzip, pack->hashSize);
buildBuffer[i].name = FS_AppendStringBuffer(namesBuffer, filename_inzip);
buildBuffer[i].name = Z_StringPoolAdd(namesBuffer, filename_inzip);
// store the file position in the zip
buildBuffer[i].pos = unzGetOffset(uf);
buildBuffer[i].len = file_info.uncompressed_size;
Expand Down Expand Up @@ -3182,7 +3136,7 @@ static void FS_AddGameDirectory( const char *path, const char *dir, qboolean ass
if (!found) {
// server has no interest in the file
unzClose(pak->handle);
FS_FreeStringBuffer(pak->namesBuffer);
Z_StringPoolFree(pak->namesBuffer);
Z_Free(pak->buildBuffer);
Z_Free(pak);
continue;
Expand Down Expand Up @@ -3440,7 +3394,7 @@ void FS_Shutdown( qboolean closemfp, qboolean keepModuleFiles ) {

if ( p->pack ) {
unzClose(p->pack->handle);
FS_FreeStringBuffer( p->pack->namesBuffer );
Z_StringPoolFree( p->pack->namesBuffer );
Z_Free( p->pack->buildBuffer );
Z_Free( p->pack );
}
Expand Down
7 changes: 7 additions & 0 deletions src/qcommon/qcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,13 @@ MISC

const char *CopyString( const char *in );
const char *CopyString( const char *in, memtag_t eTag );

struct stringPool_s;
typedef struct stringPool_s stringPool_t;
stringPool_t *Z_StringPoolNew(unsigned int size, memtag_t eTag);
void Z_StringPoolFree(stringPool_t * pool);
const char *Z_StringPoolAdd(stringPool_t * pool, const char * string);

void Info_Print( const char *s );

void Com_BeginRedirect (char *buffer, size_t buffersize, void (*flush)(char *), qboolean silent);
Expand Down

0 comments on commit a50ec9f

Please sign in to comment.