From 6e30c51fac30f01be566ec7c092c0cb023f5d458 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Oct 2017 22:17:12 -0700 Subject: [PATCH] Add a method to start async loading multiple buffers at once Currently it should try to avoid loading more than 16 buffers at once due to the fixed lockless rinbuffer size. Might be a good idea to use an atomic linked list so that it can grow as needed (although having too many files open at once while waiting to decode could be an issue). --- include/AL/alure2.h | 19 +++++++++++++++++++ src/context.cpp | 23 ++++++++++++++++++++++- src/context.h | 1 + 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/AL/alure2.h b/include/AL/alure2.h index 05fcd25..889ed41 100644 --- a/include/AL/alure2.h +++ b/include/AL/alure2.h @@ -649,6 +649,25 @@ public: Buffer getBufferAsync(const String &name); /** + * Creates and caches Buffers for the given audio file or resource names. + * Duplicate names or names of buffers already cached are ignored. + * + * The Buffer objects will be scheduled for loading asynchronously, and + * should be retrieved later when needed using getBufferAsync or getBuffer. + * Buffers that cannot be loaded, for example due to an unsupported format, + * will be ignored and a later call to getBuffer or getBufferAsync will + * throw an exception. Precached buffers must also be cleaned up with calls + * to removeBuffer when no longer needed. + * + * Note that you should avoid trying to asynchronously cache more than 16 + * buffers at a time. The internal ringbuffer used to communicate with the + * background thread can only hold 16 async load requests, and trying to + * add more will cause the call to stall until the background thread + * completes some loads for more to be filled in. + */ + void precacheBuffersAsync(ArrayView names); + + /** * Creates and caches a Buffer using the given name. The name may alias an * audio file, but it must not currently exist in the buffer cache. As with * other cached buffers, removeBuffer must be used to remove it from the diff --git a/src/context.cpp b/src/context.cpp index afa4a59..1aaad10 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -743,7 +743,7 @@ BufferOrExceptT ALContext::doCreateBufferAsync(const String &name, Vector(this, bid, srate, chans, type, false, name); @@ -810,6 +810,26 @@ Buffer ALContext::getBufferAsync(const String &name) return *buffer; } +void ALContext::precacheBuffersAsync(ArrayView names) +{ + CheckContext(this); + + auto hasher = std::hash(); + for(const String &name : names) + { + auto iter = std::lower_bound(mBuffers.begin(), mBuffers.end(), hasher(name), + [hasher](const UniquePtr &lhs, size_t rhs) -> bool + { return hasher(lhs->getName()) < rhs; } + ); + if(iter != mBuffers.end() && (*iter)->getName() == name) + continue; + + doCreateBufferAsync(name, iter, createDecoder(name)); + } + mWakeMutex.lock(); mWakeMutex.unlock(); + mWakeThread.notify_all(); +} + Buffer ALContext::createBufferFrom(const String &name, SharedPtr decoder) { CheckContext(this); @@ -1095,6 +1115,7 @@ DECL_THUNK0(const Vector&, Context, getAvailableResamplers,) DECL_THUNK0(ALsizei, Context, getDefaultResamplerIndex, const) DECL_THUNK1(Buffer, Context, getBuffer,, const String&) DECL_THUNK1(Buffer, Context, getBufferAsync,, const String&) +DECL_THUNK1(void, Context, precacheBuffersAsync,, ArrayView) DECL_THUNK2(Buffer, Context, createBufferFrom,, const String&, SharedPtr) DECL_THUNK2(Buffer, Context, createBufferAsyncFrom,, const String&, SharedPtr) DECL_THUNK1(void, Context, removeBuffer,, const String&) diff --git a/src/context.h b/src/context.h index 01aec59..87d70bd 100644 --- a/src/context.h +++ b/src/context.h @@ -279,6 +279,7 @@ public: Buffer getBuffer(const String &name); Buffer getBufferAsync(const String &name); + void precacheBuffersAsync(ArrayView names); Buffer createBufferFrom(const String &name, SharedPtr decoder); Buffer createBufferAsyncFrom(const String &name, SharedPtr decoder); void removeBuffer(const String &name); -- 2.11.4.GIT