mirror of https://github.com/encounter/SDL.git
Added SDL_ReserveSpaceInDataQueue() to make space without copying data.
This commit is contained in:
parent
18d9b23c65
commit
2e2572a4f1
|
@ -137,6 +137,40 @@ SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack)
|
||||||
SDL_FreeDataQueueList(packet); /* free extra packets */
|
SDL_FreeDataQueueList(packet); /* free extra packets */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDL_DataQueuePacket *
|
||||||
|
AllocateDataQueuePacket(SDL_DataQueue *queue)
|
||||||
|
{
|
||||||
|
SDL_DataQueuePacket *packet;
|
||||||
|
|
||||||
|
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! */
|
||||||
|
packet = (SDL_DataQueuePacket *) SDL_malloc(sizeof (SDL_DataQueuePacket) + queue->packet_size);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
|
SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
|
||||||
{
|
{
|
||||||
|
@ -161,14 +195,8 @@ SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
|
||||||
SDL_assert(!packet || (packet->datalen <= packet_size));
|
SDL_assert(!packet || (packet->datalen <= packet_size));
|
||||||
if (!packet || (packet->datalen >= packet_size)) {
|
if (!packet || (packet->datalen >= packet_size)) {
|
||||||
/* tail packet missing or completely full; we need a new packet. */
|
/* tail packet missing or completely full; we need a new packet. */
|
||||||
packet = queue->pool;
|
packet = AllocateDataQueuePacket(queue);
|
||||||
if (packet != NULL) {
|
if (!packet) {
|
||||||
/* we have one available in the pool. */
|
|
||||||
queue->pool = packet->next;
|
|
||||||
} else {
|
|
||||||
/* Have to allocate a new one! */
|
|
||||||
packet = (SDL_DataQueuePacket *) SDL_malloc(sizeof (SDL_DataQueuePacket) + packet_size);
|
|
||||||
if (packet == NULL) {
|
|
||||||
/* uhoh, reset so we've queued nothing new, free what we can. */
|
/* uhoh, reset so we've queued nothing new, free what we can. */
|
||||||
if (!origtail) {
|
if (!origtail) {
|
||||||
packet = queue->head; /* whole queue. */
|
packet = queue->head; /* whole queue. */
|
||||||
|
@ -182,22 +210,9 @@ SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
|
||||||
queue->pool = NULL;
|
queue->pool = NULL;
|
||||||
|
|
||||||
SDL_FreeDataQueueList(packet); /* give back what we can. */
|
SDL_FreeDataQueueList(packet); /* give back what we can. */
|
||||||
|
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
datalen = SDL_min(len, packet_size - packet->datalen);
|
datalen = SDL_min(len, packet_size - packet->datalen);
|
||||||
SDL_memcpy(packet->data + packet->datalen, data, datalen);
|
SDL_memcpy(packet->data + packet->datalen, data, datalen);
|
||||||
|
@ -256,5 +271,44 @@ SDL_CountDataQueue(SDL_DataQueue *queue)
|
||||||
return queue ? queue->queued_bytes : 0;
|
return queue ? queue->queued_bytes : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
SDL_ReserveSpaceInDataQueue(SDL_DataQueue *queue, const size_t len)
|
||||||
|
{
|
||||||
|
SDL_DataQueuePacket *packet;
|
||||||
|
|
||||||
|
if (!queue) {
|
||||||
|
SDL_InvalidParamError("queue");
|
||||||
|
return NULL;
|
||||||
|
} else if (len == 0) {
|
||||||
|
SDL_InvalidParamError("len");
|
||||||
|
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) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet->datalen = len;
|
||||||
|
queue->queued_bytes += len;
|
||||||
|
return packet->data;
|
||||||
|
}
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,21 @@ int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *data, const size_t le
|
||||||
size_t SDL_ReadFromDataQueue(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);
|
size_t SDL_CountDataQueue(SDL_DataQueue *queue);
|
||||||
|
|
||||||
|
/* this sets a section of the data queue aside (possibly allocating memory for it)
|
||||||
|
as if it's been written to, but returns a pointer to that space. You may write
|
||||||
|
to this space until a read would consume it. Writes (and other calls to this
|
||||||
|
function) will safely append their data after this reserved space and can
|
||||||
|
be in flight at the same time. There is no thread safety.
|
||||||
|
If there isn't an existing block of memory that can contain the reserved
|
||||||
|
space, one will be allocated for it. You can not (currently) allocate
|
||||||
|
a space larger than the packetlen requested in SDL_NewDataQueue.
|
||||||
|
Returned buffer is uninitialized.
|
||||||
|
This lets you avoid an extra copy in some cases, but it's safer to use
|
||||||
|
SDL_WriteToDataQueue() unless you know what you're doing.
|
||||||
|
Returns pointer to buffer of at least (len) bytes, NULL on error.
|
||||||
|
*/
|
||||||
|
void *SDL_ReserveSpaceInDataQueue(SDL_DataQueue *queue, const size_t len);
|
||||||
|
|
||||||
#endif /* SDL_dataqueue_h_ */
|
#endif /* SDL_dataqueue_h_ */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
Loading…
Reference in New Issue