SDL  2.0
SDL_dataqueue.c File Reference
#include "./SDL_internal.h"
#include "SDL.h"
#include "./SDL_dataqueue.h"
#include "SDL_assert.h"
+ Include dependency graph for SDL_dataqueue.c:

Go to the source code of this file.

Data Structures

struct  SDL_DataQueuePacket
struct  SDL_DataQueue

Functions

static void SDL_FreeDataQueueList (SDL_DataQueuePacket *packet)
SDL_DataQueueSDL_NewDataQueue (const size_t _packetlen, const size_t initialslack)
void SDL_FreeDataQueue (SDL_DataQueue *queue)
void SDL_ClearDataQueue (SDL_DataQueue *queue, const size_t slack)
static SDL_DataQueuePacketAllocateDataQueuePacket (SDL_DataQueue *queue)
int SDL_WriteToDataQueue (SDL_DataQueue *queue, const void *_data, const size_t _len)
size_t SDL_PeekIntoDataQueue (SDL_DataQueue *queue, void *_buf, const size_t _len)
size_t SDL_ReadFromDataQueue (SDL_DataQueue *queue, void *_buf, const size_t _len)
size_t SDL_CountDataQueue (SDL_DataQueue *queue)
voidSDL_ReserveSpaceInDataQueue (SDL_DataQueue *queue, const size_t len)

Function Documentation

static SDL_DataQueuePacket* AllocateDataQueuePacket ( SDL_DataQueue queue)
static

Definition at line 141 of file SDL_dataqueue.c.

References SDL_DataQueuePacket::datalen, SDL_DataQueue::head, SDL_DataQueuePacket::next, NULL, SDL_DataQueue::packet_size, SDL_DataQueue::pool, SDL_DataQueue::queued_bytes, SDL_assert, SDL_malloc, SDL_DataQueuePacket::startpos, and SDL_DataQueue::tail.

Referenced by SDL_ReserveSpaceInDataQueue(), and SDL_WriteToDataQueue().

{
SDL_assert(queue != NULL);
packet = queue->pool;
if (packet != NULL) {
/* we have one available in the pool. */
queue->pool = packet->next;
} else {
/* Have to allocate a new one! */
if (packet == NULL) {
return NULL;
}
}
packet->datalen = 0;
packet->startpos = 0;
packet->next = NULL;
SDL_assert((queue->head != NULL) == (queue->queued_bytes != 0));
if (queue->tail == NULL) {
queue->head = packet;
} else {
queue->tail->next = packet;
}
queue->tail = packet;
return packet;
}
void SDL_ClearDataQueue ( SDL_DataQueue queue,
const size_t  slack 
)

Definition at line 98 of file SDL_dataqueue.c.

References SDL_DataQueue::head, i, SDL_DataQueuePacket::next, NULL, SDL_DataQueue::packet_size, SDL_DataQueue::pool, SDL_DataQueue::queued_bytes, SDL_FreeDataQueueList(), and SDL_DataQueue::tail.

Referenced by SDL_AudioStreamClear(), and SDL_ClearQueuedAudio().

{
const size_t packet_size = queue ? queue->packet_size : 1;
const size_t slackpackets = (slack + (packet_size-1)) / packet_size;
size_t i;
if (!queue) {
return;
}
packet = queue->head;
/* merge the available pool and the current queue into one list. */
if (packet) {
queue->tail->next = queue->pool;
} else {
packet = queue->pool;
}
/* Remove the queued packets from the device. */
queue->tail = NULL;
queue->head = NULL;
queue->queued_bytes = 0;
queue->pool = packet;
/* Optionally keep some slack in the pool to reduce malloc pressure. */
for (i = 0; packet && (i < slackpackets); i++) {
prev = packet;
packet = packet->next;
}
if (prev) {
prev->next = NULL;
} else {
queue->pool = NULL;
}
SDL_FreeDataQueueList(packet); /* free extra packets */
}
size_t SDL_CountDataQueue ( SDL_DataQueue queue)

Definition at line 294 of file SDL_dataqueue.c.

References SDL_DataQueue::queued_bytes.

Referenced by SDL_AudioStreamAvailable(), SDL_BufferQueueDrainCallback(), and SDL_GetQueuedAudioSize().

{
return queue ? queue->queued_bytes : 0;
}
void SDL_FreeDataQueue ( SDL_DataQueue queue)

Definition at line 88 of file SDL_dataqueue.c.

References SDL_DataQueue::head, SDL_DataQueue::pool, SDL_free, and SDL_FreeDataQueueList().

Referenced by close_audio_device(), and SDL_FreeAudioStream().

{
if (queue) {
SDL_free(queue);
}
}
static void SDL_FreeDataQueueList ( SDL_DataQueuePacket packet)
static

Definition at line 45 of file SDL_dataqueue.c.

References SDL_DataQueuePacket::next, and SDL_free.

Referenced by SDL_ClearDataQueue(), SDL_FreeDataQueue(), and SDL_WriteToDataQueue().

{
while (packet) {
SDL_DataQueuePacket *next = packet->next;
SDL_free(packet);
packet = next;
}
}
SDL_DataQueue* SDL_NewDataQueue ( const size_t  _packetlen,
const size_t  initialslack 
)

Definition at line 58 of file SDL_dataqueue.c.

References SDL_DataQueuePacket::datalen, i, SDL_DataQueuePacket::next, NULL, SDL_DataQueue::packet_size, SDL_DataQueue::pool, SDL_malloc, SDL_OutOfMemory, SDL_zerop, and SDL_DataQueuePacket::startpos.

Referenced by open_audio_device(), and SDL_NewAudioStream().

{
if (!queue) {
return NULL;
} else {
const size_t packetlen = _packetlen ? _packetlen : 1024;
const size_t wantpackets = (initialslack + (packetlen - 1)) / packetlen;
size_t i;
SDL_zerop(queue);
queue->packet_size = packetlen;
for (i = 0; i < wantpackets; i++) {
if (packet) { /* don't care if this fails, we'll deal later. */
packet->datalen = 0;
packet->startpos = 0;
packet->next = queue->pool;
queue->pool = packet;
}
}
}
return queue;
}
size_t SDL_PeekIntoDataQueue ( SDL_DataQueue queue,
void _buf,
const size_t  _len 
)

Definition at line 229 of file SDL_dataqueue.c.

References SDL_DataQueuePacket::data, SDL_DataQueuePacket::datalen, SDL_DataQueue::head, SDL_DataQueuePacket::next, SDL_DataQueue::queued_bytes, SDL_assert, SDL_memcpy, SDL_min, and SDL_DataQueuePacket::startpos.

{
size_t len = _len;
Uint8 *buf = (Uint8 *) _buf;
Uint8 *ptr = buf;
if (!queue) {
return 0;
}
for (packet = queue->head; len && packet; packet = packet->next) {
const size_t avail = packet->datalen - packet->startpos;
const size_t cpy = SDL_min(len, avail);
SDL_assert(queue->queued_bytes >= avail);
SDL_memcpy(ptr, packet->data + packet->startpos, cpy);
ptr += cpy;
len -= cpy;
}
return (size_t) (ptr - buf);
}
size_t SDL_ReadFromDataQueue ( SDL_DataQueue queue,
void _buf,
const size_t  _len 
)

Definition at line 254 of file SDL_dataqueue.c.

References SDL_DataQueuePacket::data, SDL_DataQueuePacket::datalen, SDL_DataQueue::head, SDL_DataQueuePacket::next, NULL, SDL_DataQueue::pool, SDL_DataQueue::queued_bytes, SDL_assert, SDL_memcpy, SDL_min, SDL_DataQueuePacket::startpos, and SDL_DataQueue::tail.

Referenced by SDL_AudioStreamGet(), SDL_BufferQueueDrainCallback(), and SDL_DequeueAudio().

{
size_t len = _len;
Uint8 *buf = (Uint8 *) _buf;
Uint8 *ptr = buf;
if (!queue) {
return 0;
}
while ((len > 0) && ((packet = queue->head) != NULL)) {
const size_t avail = packet->datalen - packet->startpos;
const size_t cpy = SDL_min(len, avail);
SDL_assert(queue->queued_bytes >= avail);
SDL_memcpy(ptr, packet->data + packet->startpos, cpy);
packet->startpos += cpy;
ptr += cpy;
queue->queued_bytes -= cpy;
len -= cpy;
if (packet->startpos == packet->datalen) { /* packet is done, put it in the pool. */
queue->head = packet->next;
SDL_assert((packet->next != NULL) || (packet == queue->tail));
packet->next = queue->pool;
queue->pool = packet;
}
}
SDL_assert((queue->head != NULL) == (queue->queued_bytes != 0));
if (queue->head == NULL) {
queue->tail = NULL; /* in case we drained the queue entirely. */
}
return (size_t) (ptr - buf);
}
void* SDL_ReserveSpaceInDataQueue ( SDL_DataQueue queue,
const size_t  len 
)

Definition at line 300 of file SDL_dataqueue.c.

References AllocateDataQueuePacket(), SDL_DataQueuePacket::data, SDL_DataQueuePacket::datalen, SDL_DataQueue::head, NULL, SDL_DataQueue::packet_size, SDL_DataQueue::queued_bytes, retval, SDL_InvalidParamError, SDL_OutOfMemory, and SDL_SetError.

{
if (!queue) {
return NULL;
} else if (len == 0) {
return NULL;
} else if (len > queue->packet_size) {
SDL_SetError("len is larger than packet size");
return NULL;
}
packet = queue->head;
if (packet) {
const size_t avail = queue->packet_size - packet->datalen;
if (len <= avail) { /* we can use the space at end of this packet. */
void *retval = packet->data + packet->datalen;
packet->datalen += len;
queue->queued_bytes += len;
return retval;
}
}
/* Need a fresh packet. */
packet = AllocateDataQueuePacket(queue);
if (!packet) {
return NULL;
}
packet->datalen = len;
queue->queued_bytes += len;
return packet->data;
}
int SDL_WriteToDataQueue ( SDL_DataQueue queue,
const void _data,
const size_t  _len 
)

Definition at line 175 of file SDL_dataqueue.c.

References AllocateDataQueuePacket(), SDL_DataQueuePacket::data, SDL_DataQueuePacket::datalen, SDL_DataQueue::head, SDL_DataQueuePacket::next, NULL, SDL_DataQueue::packet_size, SDL_DataQueue::pool, SDL_DataQueue::queued_bytes, SDL_assert, SDL_FreeDataQueueList(), SDL_InvalidParamError, SDL_memcpy, SDL_min, SDL_OutOfMemory, and SDL_DataQueue::tail.

Referenced by SDL_AudioStreamPut(), SDL_AudioStreamPutInternal(), SDL_BufferQueueFillCallback(), and SDL_QueueAudio().

{
size_t len = _len;
const Uint8 *data = (const Uint8 *) _data;
const size_t packet_size = queue ? queue->packet_size : 0;
size_t origlen;
size_t datalen;
if (!queue) {
return SDL_InvalidParamError("queue");
}
orighead = queue->head;
origtail = queue->tail;
origlen = origtail ? origtail->datalen : 0;
while (len > 0) {
SDL_DataQueuePacket *packet = queue->tail;
SDL_assert(!packet || (packet->datalen <= packet_size));
if (!packet || (packet->datalen >= packet_size)) {
/* tail packet missing or completely full; we need a new packet. */
packet = AllocateDataQueuePacket(queue);
if (!packet) {
/* uhoh, reset so we've queued nothing new, free what we can. */
if (!origtail) {
packet = queue->head; /* whole queue. */
} else {
packet = origtail->next; /* what we added to existing queue. */
origtail->next = NULL;
origtail->datalen = origlen;
}
queue->head = orighead;
queue->tail = origtail;
queue->pool = NULL;
SDL_FreeDataQueueList(packet); /* give back what we can. */
return SDL_OutOfMemory();
}
}
datalen = SDL_min(len, packet_size - packet->datalen);
SDL_memcpy(packet->data + packet->datalen, data, datalen);
data += datalen;
len -= datalen;
packet->datalen += datalen;
queue->queued_bytes += datalen;
}
return 0;
}