From 85549b59b766640de6e6d2e7e8f40b1cd9960e97 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jul 2015 15:29:10 -0700 Subject: [PATCH] ring buffer: fewer mallocs during init --- src/os.cpp | 40 ++++++++++++---------------------------- src/os.hpp | 7 ++++--- src/ring_buffer.cpp | 18 +++++++----------- src/ring_buffer.hpp | 5 ++--- 4 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/os.cpp b/src/os.cpp index 3c5f3bf..8efc67c 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -132,14 +132,6 @@ pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; static int page_size; -struct SoundIoOsMirroredMemoryPrivate { - SoundIoOsMirroredMemory pub; -#if defined(SOUNDIO_OS_WINDOWS) - HANDLE handle; -#endif -}; - - double soundio_os_get_time(void) { #if defined(SOUNDIO_OS_WINDOWS) unsigned __int64 time; @@ -613,19 +605,14 @@ int soundio_os_page_size(void) { return page_size; } -struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t requested_capacity) { - SoundIoOsMirroredMemoryPrivate *m = create(); - if (!m) - return nullptr; - SoundIoOsMirroredMemory *mem = &m->pub; - +int soundio_os_init_mirrored_memory(struct SoundIoOsMirroredMemory *mem, size_t requested_capacity) { size_t actual_capacity = ceil(requested_capacity / (double)page_size) * page_size; #if defined(SOUNDIO_OS_WINDOWS) BOOL ok; HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, actual_capacity * 2, NULL); if (!hMapFile) - return nullptr; + return SoundIoErrorNoMem; for (;;) { // 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) { ok = CloseHandle(hMapFile); assert(ok); - return nullptr; + return SoundIoErrorNoMem; } // 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 { ok = CloseHandle(hMapFile); assert(ok); - return nullptr; + return SoundIoErrorNoMem; } } @@ -665,30 +652,31 @@ struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t request } else { ok = CloseHandle(hMapFile); assert(ok); - return nullptr; + return SoundIoErrorNoMem; } } + mem->priv = hMapFile; mem->address = address; break; } #else char *address = (char*)mmap(NULL, actual_capacity * 2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (address == MAP_FAILED) - return nullptr; + return SoundIoErrorNoMem; char *other_address = (char*)mmap(address, actual_capacity, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0); if (other_address != address) { munmap(address, 2 * actual_capacity); - return nullptr; + return SoundIoErrorNoMem; } other_address = (char*)mmap(address + actual_capacity, actual_capacity, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0); if (other_address != address + actual_capacity) { munmap(address, 2 * actual_capacity); - return nullptr; + return SoundIoErrorNoMem; } mem->address = address; @@ -696,24 +684,20 @@ struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t request #endif mem->capacity = actual_capacity; - return mem; + return 0; } -void soundio_os_destroy_mirrored_memory(struct SoundIoOsMirroredMemory *mem) { - if (!mem) - return; - SoundIoOsMirroredMemoryPrivate *m = (SoundIoOsMirroredMemoryPrivate *)mem; +void soundio_os_deinit_mirrored_memory(struct SoundIoOsMirroredMemory *mem) { #if defined(SOUNDIO_OS_WINDOWS) BOOL ok; ok = UnmapViewOfFile(mem->address); assert(ok); ok = UnmapViewOfFile(mem->address + mem->capacity); assert(ok); - ok = CloseHandle(m->handle); + ok = CloseHandle((HANDLE)mem->priv); assert(ok); #else int err = munmap(mem->address, 2 * mem->capacity); assert(!err); #endif - destroy(m); } diff --git a/src/os.hpp b/src/os.hpp index fc5ba95..5cb5f18 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -51,15 +51,16 @@ void soundio_os_cond_wait(struct SoundIoOsCond *cond, 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 { size_t capacity; char *address; + void *priv; }; // returned capacity might be increased from capacity to be a multiple of the // system page size -struct SoundIoOsMirroredMemory *soundio_os_create_mirrored_memory(size_t capacity); -void soundio_os_destroy_mirrored_memory(struct SoundIoOsMirroredMemory *mem); +int soundio_os_init_mirrored_memory(struct SoundIoOsMirroredMemory *mem, size_t capacity); +void soundio_os_deinit_mirrored_memory(struct SoundIoOsMirroredMemory *mem); #endif diff --git a/src/ring_buffer.cpp b/src/ring_buffer.cpp index 4fc7642..f255d98 100644 --- a/src/ring_buffer.cpp +++ b/src/ring_buffer.cpp @@ -42,7 +42,7 @@ int soundio_ring_buffer_capacity(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) { @@ -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) { - 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) { @@ -75,20 +75,16 @@ void soundio_ring_buffer_clear(struct SoundIoRingBuffer *rb) { } int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity) { - rb->mem = soundio_os_create_mirrored_memory(requested_capacity); - if (!rb->mem) { - soundio_ring_buffer_deinit(rb); - return SoundIoErrorNoMem; - } - rb->address = rb->mem->address; - rb->capacity = rb->mem->capacity; + int err; + if ((err = soundio_os_init_mirrored_memory(&rb->mem, requested_capacity))) + return err; rb->write_offset = 0; rb->read_offset = 0; + rb->capacity = rb->mem.capacity; return 0; } void soundio_ring_buffer_deinit(struct SoundIoRingBuffer *rb) { - soundio_os_destroy_mirrored_memory(rb->mem); - rb->mem = nullptr; + soundio_os_deinit_mirrored_memory(&rb->mem); } diff --git a/src/ring_buffer.hpp b/src/ring_buffer.hpp index 5abbe79..1a3c4e3 100644 --- a/src/ring_buffer.hpp +++ b/src/ring_buffer.hpp @@ -12,11 +12,10 @@ #include "os.hpp" struct SoundIoRingBuffer { - char *address; - int capacity; + SoundIoOsMirroredMemory mem; atomic_long write_offset; atomic_long read_offset; - SoundIoOsMirroredMemory *mem; + int capacity; }; int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity);