From c699ae8ab64481a7a251061fc2912916de4803de Mon Sep 17 00:00:00 2001 From: Darryl Pogue Date: Sun, 26 Jun 2011 16:14:47 -0700 Subject: [PATCH] Use hsThread for SoundBuffer preloading. --- .../PubUtilLib/plAudioCore/plSoundBuffer.cpp | 117 ++++++++---------- .../PubUtilLib/plAudioCore/plSoundBuffer.h | 38 +++++- 2 files changed, 89 insertions(+), 66 deletions(-) diff --git a/Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.cpp b/Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.cpp index 9c9bf9da..d2a0304b 100644 --- a/Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.cpp +++ b/Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.cpp @@ -40,11 +40,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plStatusLog/plStatusLog.h" #include "hsTimer.h" -static bool s_running; -static LISTDECL(plSoundBuffer, link) s_loading; -static CCritSect s_critsect; -static CEvent s_event(kEventAutoReset); - static void GetFullPath( const char filename[], char *destStr ) { char path[ kFolderIterator_MaxPath ]; @@ -79,73 +74,74 @@ static plAudioFileReader *CreateReader( hsBool fullpath, const char filename[], return reader; } -// our loading thread -static void LoadCallback(void *) +hsError plSoundPreloader::Run() { - LISTDECL(plSoundBuffer, link) templist; - while(s_running) - { - s_critsect.Enter(); - { - while(plSoundBuffer *buffer = s_loading.Head()) - { - templist.Link(buffer); - } - } - s_critsect.Leave(); - - if(!templist.Head()) - { - s_event.Wait(kEventWaitForever); - } - else - { + hsTArray templist; + + while (fRunning) + { + fCritSect.Lock(); + for (int i = fBuffers.GetCount(); i > 0; i--) + { + templist.Append(fBuffers.Pop()); + } + fCritSect.Unlock(); + + if (templist.GetCount() == 0) + { + fEvent.Wait(); + } + else + { plAudioFileReader *reader = nil; - while(plSoundBuffer *buffer = templist.Head()) - { - if(buffer->GetData()) - { - reader = CreateReader(true, buffer->GetFileName(), buffer->GetAudioReaderType(), buffer->GetReaderSelect()); + for (int i = templist.GetCount(); i > 0; i--) + { + plSoundBuffer* buf = templist.Pop(); + + if (buf->GetData()) + { + reader = CreateReader(true, buf->GetFileName(), buf->GetAudioReaderType(), buf->GetReaderSelect()); if( reader ) { - unsigned readLen = buffer->GetAsyncLoadLength() ? buffer->GetAsyncLoadLength() : buffer->GetDataLength(); - reader->Read( readLen, buffer->GetData() ); - buffer->SetAudioReader(reader); // give sound buffer reader, since we may need it later + unsigned readLen = buf->GetAsyncLoadLength() ? buf->GetAsyncLoadLength() : buf->GetDataLength(); + reader->Read( readLen, buf->GetData() ); + buf->SetAudioReader(reader); // give sound buffer reader, since we may need it later } else - buffer->SetError(); - } - - templist.Unlink(buffer); - buffer->SetLoaded(true); - } - } - } + { + buf->SetError(); + } + } + + buf->SetLoaded(true); + } + } + } // we need to be sure that all buffers are removed from our load list when shutting this thread down or we will hang, // since the sound buffer will wait to be destroyed until it is marked as loaded - s_critsect.Enter(); - { - while(plSoundBuffer *buffer = s_loading.Head()) - { - buffer->SetLoaded(true); - s_loading.Unlink(buffer); - } - } - s_critsect.Leave(); + fCritSect.Lock(); + for (int i = fBuffers.GetCount(); i > 0; i--) + { + plSoundBuffer* buf = fBuffers.Pop(); + buf->SetLoaded(true); + } + fCritSect.Unlock(); + + return hsOK; } +static plSoundPreloader gLoaderThread; + void plSoundBuffer::Init() { - s_running = true; - _beginthread(LoadCallback, 0, 0); + gLoaderThread.Start(); } void plSoundBuffer::Shutdown() { - s_running = false; - s_event.Signal(); + gLoaderThread.Stop(); } //// Constructor/Destructor ////////////////////////////////////////////////// @@ -175,7 +171,6 @@ plSoundBuffer::~plSoundBuffer() } } - ASSERT(!link.IsLinked()); delete [] fFileName; UnLoad(); } @@ -342,7 +337,7 @@ void plSoundBuffer::IGetFullPath( char *destStr ) // While a file is loading(fLoading == true, and fLoaded == false) a buffer, no paremeters of the buffer should be modified. plSoundBuffer::ELoadReturnVal plSoundBuffer::AsyncLoad(plAudioFileReader::StreamType type, unsigned length /* = 0 */ ) { - if(!s_running) + if(!gLoaderThread.IsRunning()) return kError; // we cannot load the data since the load thread is no longer running if(!fLoading && !fLoaded) { @@ -354,13 +349,9 @@ plSoundBuffer::ELoadReturnVal plSoundBuffer::AsyncLoad(plAudioFileReader::Stream if( fData == nil ) return kError; } - s_critsect.Enter(); - { - fLoading = true; - s_loading.Link(this); - } - s_critsect.Leave(); - s_event.Signal(); + + gLoaderThread.AddBuffer(this); + fLoading = true; } if(fLoaded) { diff --git a/Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.h b/Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.h index 2dfc90e6..b35f7534 100644 --- a/Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.h +++ b/Sources/Plasma/PubUtilLib/plAudioCore/plSoundBuffer.h @@ -39,7 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnKeyedObject/hsKeyedObject.h" #include "plAudioCore.h" #include "plAudioFileReader.h" -#include "pnUtils/pnUtils.h" +#include "hsThread.h" //// Class Definition //////////////////////////////////////////////////////// @@ -55,8 +55,6 @@ public: CLASSNAME_REGISTER( plSoundBuffer ); GETINTERFACE_ANY( plSoundBuffer, hsKeyedObject ); - LINK(plSoundBuffer) link; - enum Flags { kIsExternal = 0x0001, @@ -143,4 +141,38 @@ protected: plAudioFileReader *IGetReader( hsBool fullpath ); }; + +class plSoundPreloader : public hsThread +{ +protected: + hsTArray fBuffers; + hsEvent fEvent; + bool fRunning; + hsMutex fCritSect; + +public: + virtual hsError Run(); + + virtual void Start() { + fRunning = true; + hsThread::Start(); + } + + virtual void Stop() { + fRunning = false; + fEvent.Signal(); + hsThread::Stop(); + } + + bool IsRunning() const { return fRunning; } + + void AddBuffer(plSoundBuffer* buffer) { + fCritSect.Lock(); + fBuffers.Push(buffer); + fCritSect.Unlock(); + + fEvent.Signal(); + } +}; + #endif //_plSoundBuffer_h