forked from len0rd/rockbox
Extend buflib to support shifting space out off the buffer for other use, and returning space to the buffer.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20952 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
d59bff092d
commit
c909878f94
2 changed files with 53 additions and 0 deletions
|
@ -61,6 +61,7 @@ buflib_init(struct buflib_context *ctx, void *buf, size_t size)
|
||||||
ctx->last_handle = bd_buf + size;
|
ctx->last_handle = bd_buf + size;
|
||||||
ctx->first_free_handle = bd_buf + size - 1;
|
ctx->first_free_handle = bd_buf + size - 1;
|
||||||
ctx->first_free_block = bd_buf;
|
ctx->first_free_block = bd_buf;
|
||||||
|
ctx->buf_start = bd_buf;
|
||||||
/* A marker is needed for the end of allocated data, to make sure that it
|
/* A marker is needed for the end of allocated data, to make sure that it
|
||||||
* does not collide with the handle table, and to detect end-of-buffer.
|
* does not collide with the handle table, and to detect end-of-buffer.
|
||||||
*/
|
*/
|
||||||
|
@ -167,6 +168,53 @@ buflib_compact(struct buflib_context *ctx)
|
||||||
return ret || shift;
|
return ret || shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Shift buffered items by size units, and update handle pointers. The shift
|
||||||
|
* value must be determined to be safe *before* calling.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
buflib_buffer_shift(struct buflib_context *ctx, int shift)
|
||||||
|
{
|
||||||
|
rb->memmove(ctx->buf_start + shift, ctx->buf_start,
|
||||||
|
(ctx->alloc_end - ctx->buf_start) * sizeof(union buflib_data));
|
||||||
|
union buflib_data *ptr;
|
||||||
|
for (ptr = ctx->last_handle; ptr < ctx->handle_table; ptr++)
|
||||||
|
if (ptr->ptr)
|
||||||
|
ptr->ptr += shift;
|
||||||
|
ctx->first_free_block += shift;
|
||||||
|
ctx->buf_start += shift;
|
||||||
|
ctx->alloc_end += shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift buffered items up by size bytes, or as many as possible if size == 0.
|
||||||
|
* Set size to the number of bytes freed.
|
||||||
|
*/
|
||||||
|
void*
|
||||||
|
buflib_buffer_out(struct buflib_context *ctx, size_t *size)
|
||||||
|
{
|
||||||
|
if (!ctx->compact)
|
||||||
|
buflib_compact(ctx);
|
||||||
|
size_t avail = ctx->last_handle - ctx->alloc_end;
|
||||||
|
size_t avail_b = avail * sizeof(union buflib_data);
|
||||||
|
if (*size && *size < avail_b)
|
||||||
|
{
|
||||||
|
avail = (*size + sizeof(union buflib_data) - 1)
|
||||||
|
/ sizeof(union buflib_data);
|
||||||
|
avail_b = avail * sizeof(union buflib_data);
|
||||||
|
}
|
||||||
|
*size = avail_b;
|
||||||
|
void *ret = ctx->buf_start;
|
||||||
|
buflib_buffer_shift(ctx, avail);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift buffered items down by size bytes */
|
||||||
|
void
|
||||||
|
buflib_buffer_in(struct buflib_context *ctx, int size)
|
||||||
|
{
|
||||||
|
size /= sizeof(union buflib_data);
|
||||||
|
buflib_buffer_shift(ctx, -size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate a buffer of size bytes, returning a handle for it */
|
/* Allocate a buffer of size bytes, returning a handle for it */
|
||||||
int
|
int
|
||||||
buflib_alloc(struct buflib_context *ctx, size_t size)
|
buflib_alloc(struct buflib_context *ctx, size_t size)
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct buflib_context
|
||||||
union buflib_data *first_free_handle;
|
union buflib_data *first_free_handle;
|
||||||
union buflib_data *last_handle;
|
union buflib_data *last_handle;
|
||||||
union buflib_data *first_free_block;
|
union buflib_data *first_free_block;
|
||||||
|
union buflib_data *buf_start;
|
||||||
union buflib_data *alloc_end;
|
union buflib_data *alloc_end;
|
||||||
bool compact;
|
bool compact;
|
||||||
};
|
};
|
||||||
|
@ -45,6 +46,10 @@ struct buflib_context
|
||||||
void buflib_init(struct buflib_context *context, void *buf, size_t size);
|
void buflib_init(struct buflib_context *context, void *buf, size_t size);
|
||||||
int buflib_alloc(struct buflib_context *context, size_t size);
|
int buflib_alloc(struct buflib_context *context, size_t size);
|
||||||
void buflib_free(struct buflib_context *context, int handle);
|
void buflib_free(struct buflib_context *context, int handle);
|
||||||
|
void* buflib_buffer_out(struct buflib_context *ctx, size_t *size);
|
||||||
|
void buflib_buffer_in(struct buflib_context *ctx, int size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* always_inline is due to this not getting inlined when not optimizing, which
|
/* always_inline is due to this not getting inlined when not optimizing, which
|
||||||
* leads to an unresolved reference since it doesn't exist as a non-inline
|
* leads to an unresolved reference since it doesn't exist as a non-inline
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue