From 4ff7bfd2d8c5e94e61fbbb7afe57f98037a5383e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 Jul 2019 01:05:54 -0700 Subject: Use atomics for the picture queue --- examples/alffplay.cpp | 64 ++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/examples/alffplay.cpp b/examples/alffplay.cpp index 625c63a6..ccdfd51f 100644 --- a/examples/alffplay.cpp +++ b/examples/alffplay.cpp @@ -348,14 +348,14 @@ struct VideoState { nanoseconds mPts{nanoseconds::min()}; }; std::array mPictQ; - size_t mPictQSize{0u}, mPictQRead{0u}, mPictQWrite{1u}; + std::atomic mPictQRead{0u}, mPictQWrite{1u}; std::mutex mPictQMutex; std::condition_variable mPictQCond; SDL_Texture *mImage{nullptr}; int mWidth{0}, mHeight{0}; /* Logical image size (actual size may be larger) */ - bool mFirstUpdate{true}; + std::atomic mEOS{false}; std::atomic mFinalUpdate{false}; @@ -1155,37 +1155,38 @@ void VideoState::display(SDL_Window *screen, SDL_Renderer *renderer) */ void VideoState::updateVideo(SDL_Window *screen, SDL_Renderer *renderer) { - Picture *vp{&mPictQ[mPictQRead]}; + size_t read_idx{mPictQRead.load(std::memory_order_relaxed)}; + Picture *vp{&mPictQ[read_idx]}; - std::unique_lock lock{mPictQMutex}; auto clocktime = mMovie.getMasterClock(); - bool updated{false}; - while(mPictQSize > 0) + while(1) { - size_t nextIdx{(mPictQRead+1)%mPictQ.size()}; - Picture *nextvp{&mPictQ[nextIdx]}; + size_t next_idx{(read_idx+1)%mPictQ.size()}; + if(next_idx == mPictQWrite.load(std::memory_order_acquire)) + break; + Picture *nextvp{&mPictQ[next_idx]}; if(clocktime < nextvp->mPts) break; vp = nextvp; updated = true; - - mPictQRead = nextIdx; - --mPictQSize; + read_idx = next_idx; } if(mMovie.mQuit.load(std::memory_order_relaxed)) { if(mEOS) mFinalUpdate = true; - lock.unlock(); + mPictQRead.store(read_idx, std::memory_order_release); + std::unique_lock{mPictQMutex}.unlock(); mPictQCond.notify_all(); return; } - lock.unlock(); if(updated) { + mPictQRead.store(read_idx, std::memory_order_release); + std::unique_lock{mPictQMutex}.unlock(); mPictQCond.notify_all(); /* allocate or resize the buffer! */ @@ -1282,13 +1283,12 @@ void VideoState::updateVideo(SDL_Window *screen, SDL_Renderer *renderer) } if(mEOS.load(std::memory_order_acquire)) { - lock.lock(); - if(mPictQSize == 0) + if((read_idx+1)%mPictQ.size() == mPictQWrite.load(std::memory_order_acquire)) { mFinalUpdate = true; + std::unique_lock{mPictQMutex}.unlock(); mPictQCond.notify_all(); } - lock.unlock(); } } @@ -1305,7 +1305,9 @@ int VideoState::handler() while(!mMovie.mQuit.load(std::memory_order_relaxed)) { - Picture *vp{&mPictQ[mPictQWrite]}; + size_t write_idx{mPictQWrite.load(std::memory_order_relaxed)}; + Picture *vp{&mPictQ[write_idx]}; + { std::unique_lock lock{mPackets.getMutex()}; AVPacket *lastpkt{}; @@ -1342,19 +1344,22 @@ int VideoState::handler() /* Put the frame in the queue to be loaded into a texture and displayed * by the rendering thread. */ - std::unique_lock lock{mPictQMutex}; - mPictQWrite = (mPictQWrite+1)%mPictQ.size(); - ++mPictQSize; + write_idx = (write_idx+1)%mPictQ.size(); + mPictQWrite.store(write_idx, std::memory_order_release); - /* Wait until we have space for a new pic */ - while(mPictQSize >= (mPictQ.size()-1) && !mMovie.mQuit.load(std::memory_order_relaxed)) - mPictQCond.wait(lock); + if(write_idx == mPictQRead.load(std::memory_order_acquire)) + { + /* Wait until we have space for a new pic */ + std::unique_lock lock{mPictQMutex}; + while(write_idx == mPictQRead.load(std::memory_order_acquire) && + !mMovie.mQuit.load(std::memory_order_relaxed)) + mPictQCond.wait(lock); + } } mEOS = true; std::unique_lock lock{mPictQMutex}; - while(!mFinalUpdate) - mPictQCond.wait(lock); + while(!mFinalUpdate) mPictQCond.wait(lock); return 0; } @@ -1655,7 +1660,8 @@ int main(int argc, char *argv[]) return 1; } - { auto device = alcGetContextsDevice(alcGetCurrentContext()); + { + auto device = alcGetContextsDevice(alcGetCurrentContext()); if(alcIsExtensionPresent(device, "ALC_SOFT_device_clock")) { std::cout<< "Found ALC_SOFT_device_clock" <(movState->getDuration()); - std::cout<< "\r "<