#include <string.h>
/*
- * Allocate memory on the queue. Returns NULL if allocation failed for any
- * any reason.
+ * Copy q1 to q2, and reorganize the memory to correct for q2's new size
*/
-vg_queue_frame *vg_queue_alloc( vg_queue *q, u32 size )
+void vg_queue_copy_upgrade( vg_queue *q1, vg_queue *q2 )
{
- u32 total = vg_align8(size) + sizeof(vg_queue_frame);
- vg_queue_frame *frame = NULL;
+ VG_ASSERT( q2->size >= q1->size );
+ if( q1->allocation_count == 0 )
+ {
+ q2->head_offset = 0;
+ q2->tail_offset = 0;
+ q2->allocation_count = 0;
+ return;
+ }
+
+ vg_queue_item *head = q1->buffer + q1->head_offset;
+ u32 end = q1->head_offset + head->alloc_size,
+ start = q1->tail_offset;
+
+ q2->allocation_count = q1->allocation_count;
+ q2->tail_offset = 0;
+ if( start < end )
+ {
+ u32 r0 = end-start;
+ memcpy( q2->buffer, q1->buffer+start, r0 );
+ q2->head_offset = r0 - head->alloc_size;
+ }
+ else
+ {
+ u32 r0 = q1->size - start;
+ memcpy( q2->buffer, q1->buffer+start, r0 );
+ memcpy( q2->buffer + r0, q1->buffer, end );
+ q2->head_offset = r0 + end - head->alloc_size;
+ }
+}
+
+void *vg_queue_data( vg_queue *q, u32 offset )
+{
+ vg_queue_item *item = q->buffer + offset;
+ return item->data;
+}
+
+void *vg_queue_tail_data( vg_queue *q )
+{
+ if( q->allocation_count )
+ {
+ return vg_queue_data( q, q->tail_offset );
+ }
+ else
+ return NULL;
+}
+
+/*
+ * Allocate memory on the queue. Returns NULL if allocation failed for any reason & out_offset undefined
+ */
+void *vg_queue_alloc( vg_queue *q, u32 size, u32 *out_offset )
+{
+ u32 total = vg_align8(size) + sizeof(vg_queue_item);
if( total > q->size )
return NULL;
- if( q->head )
+ u32 new_item_offset;
+ if( q->allocation_count )
{
- u32 end = ((u8 *)q->head - q->buffer) + q->head->alloc_size,
- start = ((u8 *)q->tail - q->buffer),
+ vg_queue_item *head = q->buffer + q->head_offset;
+ u32 end = q->head_offset + head->alloc_size,
+ start = q->tail_offset,
r0 = 0,
r1 = 0;
- if( start < end ){
- r0 = q->size-end;
+ if( start < end )
+ {
+ r0 = q->size - end;
r1 = start;
}
else
r0 = start - end;
- if( total < r0 ){
- frame = (vg_queue_frame *)(q->buffer + end);
- }
- else {
- if( total < r1 ){
- q->head->alloc_size += r0;
- frame = (vg_queue_frame *)q->buffer;
+ if( total < r0 )
+ new_item_offset = end;
+ else
+ {
+ if( total < r1 )
+ {
+ head->alloc_size += r0;
+ new_item_offset = 0;
+ }
+ else
+ {
+ /* Full */
+ return NULL;
}
}
-
- if( !frame ) return NULL;
}
- else{
- frame = (vg_queue_frame *)q->buffer;
- q->tail = frame;
+ else
+ {
+ new_item_offset = 0;
+ q->tail_offset = 0;
}
- memset( frame, 0, sizeof(vg_queue_frame) );
+ vg_queue_item *item = (vg_queue_item *)(q->buffer + new_item_offset);
+ memset( item, 0, sizeof(vg_queue_item) );
+ item->alloc_size = total;
+ item->size = size;
- q->head = frame;
- frame->alloc_size = total;
- frame->size = size;
+ q->head_offset = new_item_offset;
+ q->allocation_count ++;
- return frame;
+ if( out_offset )
+ *out_offset = new_item_offset;
+ return item->data;
}
/*
*/
void vg_queue_pop( vg_queue *q )
{
- if( q->head == q->tail ){
- q->head = NULL;
- q->tail = NULL;
+ VG_ASSERT( q->allocation_count );
+ q->allocation_count --;
+
+ if( q->head_offset == q->tail_offset )
+ {
+ q->head_offset = 0;
+ q->tail_offset = 0;
return;
}
- u32 start = ((u8 *)q->tail - q->buffer);
- start += q->tail->alloc_size;
+ vg_queue_item *tail = q->buffer + q->tail_offset;
+ u32 start = q->tail_offset + tail->alloc_size;
if( start == q->size )
start = 0;
- q->tail = (vg_queue_frame *)(q->buffer + start);
+ q->tail_offset = start;
}
#pragma once
+#define VG_MEM_QUEUE_INVALID 0xffffffff
+
typedef struct vg_queue vg_queue;
-typedef struct vg_queue_frame vg_queue_frame;
+typedef struct vg_queue_item vg_queue_item;
-struct vg_queue_frame
+struct vg_queue_item
{
u32 alloc_size,size;
u8 data[];
struct vg_queue
{
- u8 *buffer;
+ void *buffer;
u32 size;
-
- vg_queue_frame *head, *tail;
+ u32 head_offset, tail_offset;
+ u32 allocation_count;
};
-vg_queue_frame *vg_queue_alloc( vg_queue *q, u32 size );
+void *vg_queue_alloc( vg_queue *q, u32 size, u32 *out_offset );
+
+void *vg_queue_data( vg_queue *q, u32 offset );
+void *vg_queue_tail_data( vg_queue *q );
+
void vg_queue_pop( vg_queue *q );
+void vg_queue_copy_upgrade( vg_queue *q1, vg_queue *q2 );