mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-31 22:45:48 +00:00
99 lines
2.9 KiB
C
99 lines
2.9 KiB
C
/*
|
|
* Copyright (c) 2015 Andrew Kelley
|
|
*
|
|
* This file is part of libsoundio, which is MIT licensed.
|
|
* See http://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "ring_buffer.h"
|
|
#include "soundio_private.h"
|
|
#include "util.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
struct SoundIoRingBuffer *soundio_ring_buffer_create(struct SoundIo *soundio, int requested_capacity) {
|
|
struct SoundIoRingBuffer *rb = ALLOCATE(struct SoundIoRingBuffer, 1);
|
|
|
|
assert(requested_capacity > 0);
|
|
|
|
if (!rb) {
|
|
soundio_ring_buffer_destroy(rb);
|
|
return NULL;
|
|
}
|
|
|
|
if (soundio_ring_buffer_init(rb, requested_capacity)) {
|
|
soundio_ring_buffer_destroy(rb);
|
|
return NULL;
|
|
}
|
|
|
|
return rb;
|
|
}
|
|
|
|
void soundio_ring_buffer_destroy(struct SoundIoRingBuffer *rb) {
|
|
if (!rb)
|
|
return;
|
|
|
|
soundio_ring_buffer_deinit(rb);
|
|
|
|
free(rb);
|
|
}
|
|
|
|
int soundio_ring_buffer_capacity(struct SoundIoRingBuffer *rb) {
|
|
return rb->capacity;
|
|
}
|
|
|
|
char *soundio_ring_buffer_write_ptr(struct SoundIoRingBuffer *rb) {
|
|
unsigned long write_offset = SOUNDIO_ATOMIC_LOAD(rb->write_offset);
|
|
return rb->mem.address + (write_offset % rb->capacity);
|
|
}
|
|
|
|
void soundio_ring_buffer_advance_write_ptr(struct SoundIoRingBuffer *rb, int count) {
|
|
SOUNDIO_ATOMIC_FETCH_ADD(rb->write_offset, count);
|
|
assert(soundio_ring_buffer_fill_count(rb) >= 0);
|
|
}
|
|
|
|
char *soundio_ring_buffer_read_ptr(struct SoundIoRingBuffer *rb) {
|
|
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
|
|
return rb->mem.address + (read_offset % rb->capacity);
|
|
}
|
|
|
|
void soundio_ring_buffer_advance_read_ptr(struct SoundIoRingBuffer *rb, int count) {
|
|
SOUNDIO_ATOMIC_FETCH_ADD(rb->read_offset, count);
|
|
assert(soundio_ring_buffer_fill_count(rb) >= 0);
|
|
}
|
|
|
|
int soundio_ring_buffer_fill_count(struct SoundIoRingBuffer *rb) {
|
|
// Whichever offset we load first might have a smaller value. So we load
|
|
// the read_offset first.
|
|
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
|
|
unsigned long write_offset = SOUNDIO_ATOMIC_LOAD(rb->write_offset);
|
|
int count = write_offset - read_offset;
|
|
assert(count >= 0);
|
|
assert(count <= rb->capacity);
|
|
return count;
|
|
}
|
|
|
|
int soundio_ring_buffer_free_count(struct SoundIoRingBuffer *rb) {
|
|
return rb->capacity - soundio_ring_buffer_fill_count(rb);
|
|
}
|
|
|
|
void soundio_ring_buffer_clear(struct SoundIoRingBuffer *rb) {
|
|
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
|
|
SOUNDIO_ATOMIC_STORE(rb->write_offset, read_offset);
|
|
}
|
|
|
|
int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity) {
|
|
int err;
|
|
if ((err = soundio_os_init_mirrored_memory(&rb->mem, requested_capacity)))
|
|
return err;
|
|
SOUNDIO_ATOMIC_STORE(rb->write_offset, 0);
|
|
SOUNDIO_ATOMIC_STORE(rb->read_offset, 0);
|
|
rb->capacity = rb->mem.capacity;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void soundio_ring_buffer_deinit(struct SoundIoRingBuffer *rb) {
|
|
soundio_os_deinit_mirrored_memory(&rb->mem);
|
|
}
|