ring buffer: fewer mallocs during init

This commit is contained in:
Andrew Kelley 2015-07-27 15:29:10 -07:00
parent f37ed6ddd4
commit 85549b59b7
4 changed files with 25 additions and 45 deletions

View file

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

View file

@ -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

View file

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

View file

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