Ryujinx-libsoundio/src/ring_buffer.c
2017-10-25 06:11:45 +03:00

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);
}