148 lines
3.5 KiB
C
148 lines
3.5 KiB
C
/*
|
|
EventQueue.h
|
|
Author: Patrick Baggett <ptbaggett@762studios.com>
|
|
Created: 6/18/2012
|
|
|
|
Purpose:
|
|
|
|
Common event queue code for libsst-wm implementations
|
|
|
|
License:
|
|
|
|
This program is free software. It comes without any warranty, to
|
|
the extent permitted by applicable law. You can redistribute it
|
|
and/or modify it under the terms of the Do What The Fuck You Want
|
|
To Public License, Version 2, as published by Sam Hocevar. See
|
|
http://sam.zoy.org/wtfpl/COPYING for more details.
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifndef _EVENTQUEUE_H
|
|
#define _EVENTQUEUE_H
|
|
|
|
#include <SST/SST_WMEvent.h>
|
|
#include <SST/SST_Build.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef struct EventQueue
|
|
{
|
|
SST_WMEvent* events;
|
|
size_t head; /* Index of next item to add (i.e. unused slot) */
|
|
size_t tail; /* Index of next item to remove (i.e. used slot) */
|
|
size_t count; /* Number of items in the queue */
|
|
size_t storageSize; /* Size of the backing storage */
|
|
} EventQueue;
|
|
|
|
#define EQ_DEFAULT_SIZE 32 /* Default capacity of the event queue. It may grow beyond this. */
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Initialize an event queue structure, returning non-zero if successful */
|
|
static INLINE int InitEQ(EventQueue* q)
|
|
{
|
|
/* Allocate raw storage for event queue */
|
|
q->events = (SST_WMEvent*)malloc(EQ_DEFAULT_SIZE * sizeof(SST_WMEvent));
|
|
if(q->events == NULL)
|
|
return 0;
|
|
|
|
/* Initialize storage */
|
|
q->head = 0;
|
|
q->tail = 0;
|
|
q->count = 0;
|
|
q->storageSize = EQ_DEFAULT_SIZE;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Allocate a slot from the queue (as if adding) and return pointer. This manually
|
|
eliminates copying a SST_WMEvent structure that most "enqueue" operation require. */
|
|
static INLINE SST_WMEvent* AllocSlotInEQ(EventQueue* q)
|
|
{
|
|
SST_WMEvent* slot;
|
|
|
|
/* Need to increase capacity? */
|
|
if(q->head == q->tail && q->count == q->storageSize)
|
|
{
|
|
const size_t newSize = q->storageSize * 2;
|
|
SST_WMEvent* events;
|
|
|
|
/* Expand the queue */
|
|
events = realloc(q->events, newSize * sizeof(SST_WMEvent));
|
|
if(events == NULL)
|
|
return NULL;
|
|
|
|
/* All 'count' items from [0,tail] need to be moved to [oldSize, oldSize+count] */
|
|
if(q->tail != 0)
|
|
{
|
|
/*
|
|
1) A full queue
|
|
v--h
|
|
[G][H][A][B][C][D][E][F]
|
|
^--t
|
|
|
|
2) Resized
|
|
v--h
|
|
[G][H][A][B][C][D][E][F][ ][ ][ ][ ][ ][ ][ ][ ]
|
|
^--t
|
|
|
|
3) Shift elements from 0 to tail to end, update head ptr
|
|
v--h
|
|
[ ][ ][A][B][C][D][E][F][G][H][ ][ ][ ][ ][ ][ ]
|
|
^--t
|
|
|
|
*/
|
|
|
|
/* Shift elements */
|
|
memmove(&events[q->storageSize], &events[0], q->tail * sizeof(SST_WMEvent));
|
|
|
|
}
|
|
|
|
/* Adjust head pointer to point to next empty slot */
|
|
q->head = q->tail + q->storageSize;
|
|
|
|
/* Update storage fields */
|
|
q->storageSize = newSize;
|
|
q->events = events;
|
|
} /* if(needed to increase capacity) */
|
|
|
|
/* Get the pointer to the slot where the event may be stored */
|
|
slot = &q->events[q->head];
|
|
|
|
/* Advance the head pointer by 1 */
|
|
q->head = (q->head + 1) % q->storageSize;
|
|
q->count += 1;
|
|
|
|
/* Return the slot */
|
|
return slot;
|
|
}
|
|
|
|
static INLINE int RemoveFromEQ(EventQueue* q, SST_WMEvent* event)
|
|
{
|
|
/* Completely empty? */
|
|
if(q->head == q->tail && q->count != q->storageSize)
|
|
return 0;
|
|
|
|
/* Copy the structure */
|
|
*event = q->events[q->tail];
|
|
|
|
/* Advance the tail pointer by 1 */
|
|
q->tail = (q->tail + 1) % q->storageSize;
|
|
q->count -= 1;
|
|
|
|
/* OK */
|
|
return 1;
|
|
}
|
|
|
|
static INLINE void DestroyEQ(EventQueue* q)
|
|
{
|
|
if(q->events != NULL)
|
|
free(q->events);
|
|
}
|
|
|
|
#endif
|
|
|