--- /dev/null
+#ifndef VG_MEM_QUEUE_H
+#define VG_MEM_QUEUE_H
+
+#include "vg_mem.h"
+#include "vg_stdint.h"
+
+typedef struct vg_queue vg_queue;
+typedef struct vg_queue_frame vg_queue_frame;
+
+struct vg_queue {
+ u8 *buffer;
+ u32 size;
+
+ struct vg_queue_frame {
+ u32 alloc_size,size;
+ u8 data[];
+ }
+ *head, *tail;
+};
+
+/*
+ * Allocate memory on the queue. Returns NULL if allocation failed for any
+ * any reason.
+ */
+static vg_queue_frame *vg_queue_alloc( vg_queue *q, u32 size ){
+ u32 total = vg_align8(size) + sizeof(vg_queue_frame);
+ vg_queue_frame *frame = NULL;
+
+ if( total > q->size )
+ return NULL;
+
+ if( q->head ){
+ u32 end = ((u8 *)q->head - q->buffer) + q->head->alloc_size,
+ start = ((u8 *)q->tail - q->buffer),
+ r0 = 0,
+ r1 = 0;
+
+ 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( !frame ) return NULL;
+ }
+ else{
+ frame = (vg_queue_frame *)q->buffer;
+ q->tail = frame;
+ }
+
+ memset( frame, 0, sizeof(vg_queue_frame) );
+
+ q->head = frame;
+ frame->alloc_size = total;
+ frame->size = size;
+
+ return frame;
+}
+
+/*
+ * Free last item from queue
+ */
+static void vg_queue_pop( vg_queue *q ){
+ if( q->head == q->tail ){
+ q->head = NULL;
+ q->tail = NULL;
+ return;
+ }
+
+ u32 start = ((u8 *)q->tail - q->buffer);
+ start += q->tail->alloc_size;
+
+ if( start == q->size )
+ start = 0;
+
+ q->tail = (vg_queue_frame *)(q->buffer + start);
+}
+
+#endif /* VG_MEM_QUEUE_H */