mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-23 07:25:33 +00:00
ring buffer: fewer mallocs during init
This commit is contained in:
parent
f37ed6ddd4
commit
85549b59b7
40
src/os.cpp
40
src/os.cpp
|
@ -132,14 +132,6 @@ pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
static int page_size;
|
static int page_size;
|
||||||
|
|
||||||
struct SoundIoOsMirroredMemoryPrivate {
|
|
||||||
SoundIoOsMirroredMemory pub;
|
|
||||||
#if defined(SOUNDIO_OS_WINDOWS)
|
|
||||||
HANDLE handle;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
double soundio_os_get_time(void) {
|
double soundio_os_get_time(void) {
|
||||||
#if defined(SOUNDIO_OS_WINDOWS)
|
#if defined(SOUNDIO_OS_WINDOWS)
|
||||||
unsigned __int64 time;
|
unsigned __int64 time;
|
||||||
|
@ -613,19 +605,14 @@ int soundio_os_page_size(void) {
|
||||||
return page_size;
|
return page_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t requested_capacity) {
|
int soundio_os_init_mirrored_memory(struct SoundIoOsMirroredMemory *mem, size_t requested_capacity) {
|
||||||
SoundIoOsMirroredMemoryPrivate *m = create<SoundIoOsMirroredMemoryPrivate>();
|
|
||||||
if (!m)
|
|
||||||
return nullptr;
|
|
||||||
SoundIoOsMirroredMemory *mem = &m->pub;
|
|
||||||
|
|
||||||
size_t actual_capacity = ceil(requested_capacity / (double)page_size) * page_size;
|
size_t actual_capacity = ceil(requested_capacity / (double)page_size) * page_size;
|
||||||
|
|
||||||
#if defined(SOUNDIO_OS_WINDOWS)
|
#if defined(SOUNDIO_OS_WINDOWS)
|
||||||
BOOL ok;
|
BOOL ok;
|
||||||
HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, actual_capacity * 2, NULL);
|
HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, actual_capacity * 2, NULL);
|
||||||
if (!hMapFile)
|
if (!hMapFile)
|
||||||
return nullptr;
|
return SoundIoErrorNoMem;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// find a free address space with the correct size
|
// find a free address space with the correct size
|
||||||
|
@ -633,7 +620,7 @@ struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t request
|
||||||
if (!address) {
|
if (!address) {
|
||||||
ok = CloseHandle(hMapFile);
|
ok = CloseHandle(hMapFile);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
return nullptr;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// found a big enough address space. hopefully it will remain free
|
// found a big enough address space. hopefully it will remain free
|
||||||
|
@ -649,7 +636,7 @@ struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t request
|
||||||
} else {
|
} else {
|
||||||
ok = CloseHandle(hMapFile);
|
ok = CloseHandle(hMapFile);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
return nullptr;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,30 +652,31 @@ struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t request
|
||||||
} else {
|
} else {
|
||||||
ok = CloseHandle(hMapFile);
|
ok = CloseHandle(hMapFile);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
return nullptr;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mem->priv = hMapFile;
|
||||||
mem->address = address;
|
mem->address = address;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
char *address = (char*)mmap(NULL, actual_capacity * 2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
char *address = (char*)mmap(NULL, actual_capacity * 2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||||
if (address == MAP_FAILED)
|
if (address == MAP_FAILED)
|
||||||
return nullptr;
|
return SoundIoErrorNoMem;
|
||||||
|
|
||||||
char *other_address = (char*)mmap(address, actual_capacity, PROT_READ|PROT_WRITE,
|
char *other_address = (char*)mmap(address, actual_capacity, PROT_READ|PROT_WRITE,
|
||||||
MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
|
MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
|
||||||
if (other_address != address) {
|
if (other_address != address) {
|
||||||
munmap(address, 2 * actual_capacity);
|
munmap(address, 2 * actual_capacity);
|
||||||
return nullptr;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
other_address = (char*)mmap(address + actual_capacity, actual_capacity,
|
other_address = (char*)mmap(address + actual_capacity, actual_capacity,
|
||||||
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
|
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
|
||||||
if (other_address != address + actual_capacity) {
|
if (other_address != address + actual_capacity) {
|
||||||
munmap(address, 2 * actual_capacity);
|
munmap(address, 2 * actual_capacity);
|
||||||
return nullptr;
|
return SoundIoErrorNoMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem->address = address;
|
mem->address = address;
|
||||||
|
@ -696,24 +684,20 @@ struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t request
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mem->capacity = actual_capacity;
|
mem->capacity = actual_capacity;
|
||||||
return mem;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void soundio_os_destroy_mirrored_memory(struct SoundIoOsMirroredMemory *mem) {
|
void soundio_os_deinit_mirrored_memory(struct SoundIoOsMirroredMemory *mem) {
|
||||||
if (!mem)
|
|
||||||
return;
|
|
||||||
SoundIoOsMirroredMemoryPrivate *m = (SoundIoOsMirroredMemoryPrivate *)mem;
|
|
||||||
#if defined(SOUNDIO_OS_WINDOWS)
|
#if defined(SOUNDIO_OS_WINDOWS)
|
||||||
BOOL ok;
|
BOOL ok;
|
||||||
ok = UnmapViewOfFile(mem->address);
|
ok = UnmapViewOfFile(mem->address);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
ok = UnmapViewOfFile(mem->address + mem->capacity);
|
ok = UnmapViewOfFile(mem->address + mem->capacity);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
ok = CloseHandle(m->handle);
|
ok = CloseHandle((HANDLE)mem->priv);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
#else
|
#else
|
||||||
int err = munmap(mem->address, 2 * mem->capacity);
|
int err = munmap(mem->address, 2 * mem->capacity);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
#endif
|
#endif
|
||||||
destroy(m);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,15 +51,16 @@ void soundio_os_cond_wait(struct SoundIoOsCond *cond,
|
||||||
|
|
||||||
int soundio_os_page_size(void);
|
int soundio_os_page_size(void);
|
||||||
|
|
||||||
// The size of this struct is not part of the API or ABI.
|
// You may rely on the size of this struct as part of the API and ABI.
|
||||||
struct SoundIoOsMirroredMemory {
|
struct SoundIoOsMirroredMemory {
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
char *address;
|
char *address;
|
||||||
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
// returned capacity might be increased from capacity to be a multiple of the
|
// returned capacity might be increased from capacity to be a multiple of the
|
||||||
// system page size
|
// system page size
|
||||||
struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t capacity);
|
int soundio_os_init_mirrored_memory(struct SoundIoOsMirroredMemory *mem, size_t capacity);
|
||||||
void soundio_os_destroy_mirrored_memory(struct SoundIoOsMirroredMemory *mem);
|
void soundio_os_deinit_mirrored_memory(struct SoundIoOsMirroredMemory *mem);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,7 +42,7 @@ int soundio_ring_buffer_capacity(struct SoundIoRingBuffer *rb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char *soundio_ring_buffer_write_ptr(struct SoundIoRingBuffer *rb) {
|
char *soundio_ring_buffer_write_ptr(struct SoundIoRingBuffer *rb) {
|
||||||
return rb->address + (rb->write_offset % rb->capacity);
|
return rb->mem.address + (rb->write_offset % rb->capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void soundio_ring_buffer_advance_write_ptr(struct SoundIoRingBuffer *rb, int count) {
|
void soundio_ring_buffer_advance_write_ptr(struct SoundIoRingBuffer *rb, int count) {
|
||||||
|
@ -51,7 +51,7 @@ void soundio_ring_buffer_advance_write_ptr(struct SoundIoRingBuffer *rb, int cou
|
||||||
}
|
}
|
||||||
|
|
||||||
char *soundio_ring_buffer_read_ptr(struct SoundIoRingBuffer *rb) {
|
char *soundio_ring_buffer_read_ptr(struct SoundIoRingBuffer *rb) {
|
||||||
return rb->address + (rb->read_offset % rb->capacity);
|
return rb->mem.address + (rb->read_offset % rb->capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void soundio_ring_buffer_advance_read_ptr(struct SoundIoRingBuffer *rb, int count) {
|
void soundio_ring_buffer_advance_read_ptr(struct SoundIoRingBuffer *rb, int count) {
|
||||||
|
@ -75,20 +75,16 @@ void soundio_ring_buffer_clear(struct SoundIoRingBuffer *rb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity) {
|
int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity) {
|
||||||
rb->mem = soundio_os_create_mirrored_memory(requested_capacity);
|
int err;
|
||||||
if (!rb->mem) {
|
if ((err = soundio_os_init_mirrored_memory(&rb->mem, requested_capacity)))
|
||||||
soundio_ring_buffer_deinit(rb);
|
return err;
|
||||||
return SoundIoErrorNoMem;
|
|
||||||
}
|
|
||||||
rb->address = rb->mem->address;
|
|
||||||
rb->capacity = rb->mem->capacity;
|
|
||||||
rb->write_offset = 0;
|
rb->write_offset = 0;
|
||||||
rb->read_offset = 0;
|
rb->read_offset = 0;
|
||||||
|
rb->capacity = rb->mem.capacity;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void soundio_ring_buffer_deinit(struct SoundIoRingBuffer *rb) {
|
void soundio_ring_buffer_deinit(struct SoundIoRingBuffer *rb) {
|
||||||
soundio_os_destroy_mirrored_memory(rb->mem);
|
soundio_os_deinit_mirrored_memory(&rb->mem);
|
||||||
rb->mem = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,10 @@
|
||||||
#include "os.hpp"
|
#include "os.hpp"
|
||||||
|
|
||||||
struct SoundIoRingBuffer {
|
struct SoundIoRingBuffer {
|
||||||
char *address;
|
SoundIoOsMirroredMemory mem;
|
||||||
int capacity;
|
|
||||||
atomic_long write_offset;
|
atomic_long write_offset;
|
||||||
atomic_long read_offset;
|
atomic_long read_offset;
|
||||||
SoundIoOsMirroredMemory *mem;
|
int capacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity);
|
int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity);
|
||||||
|
|
Loading…
Reference in a new issue