Skip to content

Commit

Permalink
Implemented some further optimizations to the new cbuffer code. Inste…
Browse files Browse the repository at this point in the history
…ad of freeing cbline_ts only to have to reallocate them; move them to a list of unused lines for latter re-use. Also, only resize the index when necessary (never with cbuffers of a fixed size).
  • Loading branch information
danij committed Dec 31, 2006
1 parent cae8cb7 commit 29d4bbe
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 37 deletions.
2 changes: 2 additions & 0 deletions doomsday/engine/portable/include/con_buffer.h
Expand Up @@ -47,8 +47,10 @@ typedef struct {

void *headptr;
void *tailptr;
void *unused;

cbline_t **index; // Used when indexing the buffer for read.
uint indexSize;
boolean indexGood; // If the index needs updating.

char *writebuf; // write buffer.
Expand Down
144 changes: 107 additions & 37 deletions doomsday/engine/portable/src/con_buffer.c
Expand Up @@ -51,6 +51,7 @@ typedef struct cbnode_s {

static void insertNodeAtEnd(cbuffer_t *buf, cbnode_t *newnode);
static void removeNode(cbuffer_t *buf, cbnode_t *node);
static void moveNodeForReuse(cbuffer_t *buf, cbnode_t *node);

// EXTERNAL DATA DECLARATIONS ----------------------------------------------

Expand All @@ -76,17 +77,27 @@ static cbline_t *bufferNewLine(cbuffer_t *buf)
if(!buf)
return NULL; // This is unacceptable!

// Allocate another line.
// Do we have any unused nodes we can reuse?
if(buf->unused != NULL)
{
node = buf->unused;
buf->unused = node->next;
line = node->data;
}
else
{
// Allocate another line.
line = M_Malloc(sizeof(cbline_t));
node = M_Malloc(sizeof(cbnode_t));
node->data = line;

line->text = NULL;
}
buf->numLines++;
line = M_Malloc(sizeof(cbline_t));

line->text = NULL;
line->len = 0;
line->flags = 0;

node = M_Malloc(sizeof(cbnode_t));
node->data = line;

// Link it in.
insertNodeAtEnd(buf, node);

Expand Down Expand Up @@ -161,6 +172,16 @@ static void insertNodeAtEnd(cbuffer_t *buf, cbnode_t *newnode)
insertNodeAfter(buf, buf->tailptr, newnode);
}

static void moveNodeForReuse(cbuffer_t *buf, cbnode_t *node)
{
if(buf->unused != NULL)
node->next = buf->unused;
else
node->next = NULL;
node->prev = NULL;
buf->unused = node;
}

static void removeNode(cbuffer_t *buf, cbnode_t *node)
{
if(node->prev == NULL)
Expand All @@ -173,7 +194,7 @@ static void removeNode(cbuffer_t *buf, cbnode_t *node)
else
node->next->prev = node->prev;

destroyNode(node);
moveNodeForReuse(buf, node);
}

/**
Expand All @@ -198,32 +219,48 @@ cbuffer_t *Con_NewBuffer(uint maxNumLines, uint maxLineLength, int flags)
buf->flags = flags;
buf->headptr = buf->tailptr = NULL;
buf->numLines = 0;
buf->maxLines = maxNumLines;
buf->maxLineLen = maxLineLength;
buf->writebuf = M_Calloc(buf->maxLineLen + 1);
buf->wbc = 0;
buf->wbFlags = 0;
buf->maxLines = maxNumLines;
if(buf->maxLines != 0) // not unlimited.
{ // Might as well allocate the index now.
buf->index = M_Malloc(sizeof(cbline_t*) * buf->maxLines);
buf->indexSize = buf->maxLines;
}
else
{
buf->index = NULL;
buf->indexSize = 0;
}

buf->indexGood = true; // its empty so...
buf->index = NULL;
buf->unused = NULL;

return buf;
}

/**
* Destroy an existing console history buffer.
*
* @param buf Ptr to the buffer to be destroyed.
*/
void Con_DestroyBuffer(cbuffer_t *buf)
static void clearBuffer(cbuffer_t *buf, boolean destroy)
{
if(buf)
cbnode_t *n, *np;

// Free the buffer contents.
n = buf->headptr;
while(n != NULL)
{
Con_BufferClear(buf);
M_Free(buf->writebuf);
if(buf->index)
M_Free(buf->index);
M_Free(buf);
np = n->next;
if(destroy)
destroyNode(n);
else
moveNodeForReuse(buf, n);
n = np;
}
buf->headptr = buf->tailptr = NULL;
buf->numLines = 0;

memset(buf->writebuf, 0, buf->maxLineLen + 1);
buf->wbc = 0;
}

/**
Expand All @@ -233,24 +270,39 @@ void Con_DestroyBuffer(cbuffer_t *buf)
*/
void Con_BufferClear(cbuffer_t *buf)
{
cbnode_t *n, *np;

if(!buf)
return;

// Free the buffer contents.
n = buf->headptr;
while(n != NULL)
clearBuffer(buf, false);
}

/**
* Destroy an existing console history buffer.
*
* @param buf Ptr to the buffer to be destroyed.
*/
void Con_DestroyBuffer(cbuffer_t *buf)
{
if(buf)
{
np = n->next;
destroyNode(n);
n = np;
}
buf->headptr = buf->tailptr = NULL;
buf->numLines = 0;
cbnode_t *n, *np;

memset(buf->writebuf, 0, buf->maxLineLen + 1);
buf->wbc = 0;
clearBuffer(buf, true);
M_Free(buf->writebuf);
if(buf->index)
M_Free(buf->index);

// Free any unused nodes.
n = buf->unused;
while(n)
{
np = n->next;
destroyNode(n);
n = np;
}

M_Free(buf);
}
}

/**
Expand Down Expand Up @@ -308,8 +360,13 @@ cbline_t *Con_BufferGetLine(cbuffer_t *buf, uint idx)
uint i;
cbnode_t *node;

buf->index =
M_Realloc(buf->index, sizeof(cbline_t*) * buf->numLines);
// Do we need to enlarge the index?
if(buf->indexSize < buf->numLines)
{
buf->index =
M_Realloc(buf->index, sizeof(cbline_t*) * buf->numLines);
buf->indexSize = buf->numLines;
}

i = 0;
node = buf->headptr;
Expand Down Expand Up @@ -348,8 +405,21 @@ void Con_BufferFlush(cbuffer_t *buf)
// Flush the write buffer.
//
len = strlen(buf->writebuf);
if(line->text != NULL)
{ // We are re-using an existing line so we may not need to
// reallocate at all.
uint exlen = strlen(line->text);

if(exlen < len)
line->text = M_Realloc(line->text, len + 1);
else
memset(line->text, 0, exlen);
}
else
{
line->text = M_Malloc(len + 1);
}

line->text = M_Malloc(len + 1);
strcpy(line->text, buf->writebuf);
line->text[len] = 0;
line->len = len;
Expand Down

0 comments on commit 29d4bbe

Please sign in to comment.