From 23d56cb6a1c5c766224f720cdb2fdc6094efeae0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 26 Apr 2019 18:24:26 +0200 Subject: [PATCH] output/Control: pass std::unique_lock<> to Cond::wait() --- src/output/Control.cxx | 36 +++++++++++++++++++----------------- src/output/Control.hxx | 21 +++++++++++---------- src/output/Thread.cxx | 22 +++++++++++----------- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/output/Control.cxx b/src/output/Control.cxx index ae4fa01b8..d49dbd3dc 100644 --- a/src/output/Control.cxx +++ b/src/output/Control.cxx @@ -112,10 +112,10 @@ AudioOutputControl::LockToggleEnabled() noexcept } void -AudioOutputControl::WaitForCommand() noexcept +AudioOutputControl::WaitForCommand(std::unique_lock &lock) noexcept { while (!IsCommandFinished()) - client_cond.wait(mutex); + client_cond.wait(lock); } void @@ -128,17 +128,18 @@ AudioOutputControl::CommandAsync(Command cmd) noexcept } void -AudioOutputControl::CommandWait(Command cmd) noexcept +AudioOutputControl::CommandWait(std::unique_lock &lock, + Command cmd) noexcept { CommandAsync(cmd); - WaitForCommand(); + WaitForCommand(lock); } void AudioOutputControl::LockCommandWait(Command cmd) noexcept { - const std::lock_guard protect(mutex); - CommandWait(cmd); + std::unique_lock lock(mutex); + CommandWait(lock, cmd); } void @@ -189,7 +190,8 @@ AudioOutputControl::EnableDisableAsync() } inline bool -AudioOutputControl::Open(const AudioFormat audio_format, +AudioOutputControl::Open(std::unique_lock &lock, + const AudioFormat audio_format, const MusicPipe &mp) noexcept { assert(allow_play); @@ -218,7 +220,7 @@ AudioOutputControl::Open(const AudioFormat audio_format, } } - CommandWait(Command::OPEN); + CommandWait(lock, Command::OPEN); const bool open2 = open; if (open2 && output->mixer != nullptr) { @@ -236,7 +238,7 @@ AudioOutputControl::Open(const AudioFormat audio_format, } void -AudioOutputControl::CloseWait() noexcept +AudioOutputControl::CloseWait(std::unique_lock &lock) noexcept { assert(allow_play); @@ -246,7 +248,7 @@ AudioOutputControl::CloseWait() noexcept assert(!open || !fail_timer.IsDefined()); if (open) - CommandWait(Command::CLOSE); + CommandWait(lock, Command::CLOSE); else fail_timer.Reset(); } @@ -256,15 +258,15 @@ AudioOutputControl::LockUpdate(const AudioFormat audio_format, const MusicPipe &mp, bool force) noexcept { - const std::lock_guard protect(mutex); + std::unique_lock lock(mutex); if (enabled && really_enabled) { if (force || !fail_timer.IsDefined() || fail_timer.Check(REOPEN_AFTER * 1000)) { - return Open(audio_format, mp); + return Open(lock, audio_format, mp); } } else if (IsOpen()) - CloseWait(); + CloseWait(lock); return false; } @@ -355,13 +357,13 @@ AudioOutputControl::LockRelease() noexcept mixer_auto_close()) */ mixer_auto_close(output->mixer); - const std::lock_guard protect(mutex); + std::unique_lock lock(mutex); assert(!open || !fail_timer.IsDefined()); assert(allow_play); if (IsOpen()) - CommandWait(Command::RELEASE); + CommandWait(lock, Command::RELEASE); else fail_timer.Reset(); } @@ -371,8 +373,8 @@ AudioOutputControl::LockCloseWait() noexcept { assert(!open || !fail_timer.IsDefined()); - const std::lock_guard protect(mutex); - CloseWait(); + std::unique_lock lock(mutex); + CloseWait(lock); } void diff --git a/src/output/Control.hxx b/src/output/Control.hxx index 65422de05..eb61cdf77 100644 --- a/src/output/Control.hxx +++ b/src/output/Control.hxx @@ -307,11 +307,11 @@ public: * * Caller must lock the mutex. */ - void WaitForCommand() noexcept; + void WaitForCommand(std::unique_lock &lock) noexcept; void LockWaitForCommand() noexcept { - const std::lock_guard protect(mutex); - WaitForCommand(); + std::unique_lock lock(mutex); + WaitForCommand(lock); } /** @@ -326,7 +326,7 @@ public: * * Caller must lock the mutex. */ - void CommandWait(Command cmd) noexcept; + void CommandWait(std::unique_lock &lock, Command cmd) noexcept; /** * Lock the object and execute the command synchronously. @@ -368,7 +368,7 @@ public: void LockPauseAsync() noexcept; - void CloseWait() noexcept; + void CloseWait(std::unique_lock &lock) noexcept; void LockCloseWait() noexcept; /** @@ -391,7 +391,8 @@ public: /** * Caller must lock the mutex. */ - bool Open(AudioFormat audio_format, const MusicPipe &mp) noexcept; + bool Open(std::unique_lock &lock, + AudioFormat audio_format, const MusicPipe &mp) noexcept; /** * Opens or closes the device, depending on the "enabled" @@ -522,7 +523,7 @@ private: * @return true if playback should be continued, false if a * command was issued */ - bool WaitForDelay() noexcept; + bool WaitForDelay(std::unique_lock &lock) noexcept; /** * Caller must lock the mutex. @@ -532,7 +533,7 @@ private: /** * Caller must lock the mutex. */ - bool PlayChunk() noexcept; + bool PlayChunk(std::unique_lock &lock) noexcept; /** * Plays all remaining chunks, until the tail of the pipe has @@ -546,14 +547,14 @@ private: * @return true if at least one chunk has been available, * false if the tail of the pipe was already reached */ - bool InternalPlay() noexcept; + bool InternalPlay(std::unique_lock &lock) noexcept; /** * Runs inside the OutputThread. * Caller must lock the mutex. * Handles exceptions. */ - void InternalPause() noexcept; + void InternalPause(std::unique_lock &lock) noexcept; /** * Runs inside the OutputThread. diff --git a/src/output/Thread.cxx b/src/output/Thread.cxx index ad546db1c..2b06a0b85 100644 --- a/src/output/Thread.cxx +++ b/src/output/Thread.cxx @@ -208,14 +208,14 @@ AudioOutputControl::InternalCheckClose(bool drain) noexcept * was issued */ inline bool -AudioOutputControl::WaitForDelay() noexcept +AudioOutputControl::WaitForDelay(std::unique_lock &lock) noexcept { while (true) { const auto delay = output->Delay(); if (delay <= std::chrono::steady_clock::duration::zero()) return true; - (void)wake_cond.wait_for(mutex, delay); + (void)wake_cond.wait_for(lock, delay); if (command != Command::NONE) return false; @@ -234,7 +234,7 @@ try { } inline bool -AudioOutputControl::PlayChunk() noexcept +AudioOutputControl::PlayChunk(std::unique_lock &lock) noexcept { // ensure pending tags are flushed in all cases const auto *tag = source.ReadTag(); @@ -256,7 +256,7 @@ AudioOutputControl::PlayChunk() noexcept if (skip_delay) skip_delay = false; - else if (!WaitForDelay()) + else if (!WaitForDelay(lock)) break; size_t nbytes; @@ -282,7 +282,7 @@ AudioOutputControl::PlayChunk() noexcept } inline bool -AudioOutputControl::InternalPlay() noexcept +AudioOutputControl::InternalPlay(std::unique_lock &lock) noexcept { if (!FillSourceOrClose()) /* no chunk available */ @@ -311,7 +311,7 @@ AudioOutputControl::InternalPlay() noexcept n = 0; } - if (!PlayChunk()) + if (!PlayChunk(lock)) break; } while (FillSourceOrClose()); @@ -322,7 +322,7 @@ AudioOutputControl::InternalPlay() noexcept } inline void -AudioOutputControl::InternalPause() noexcept +AudioOutputControl::InternalPause(std::unique_lock &lock) noexcept { { const ScopeUnlock unlock(mutex); @@ -334,7 +334,7 @@ AudioOutputControl::InternalPause() noexcept CommandFinished(); do { - if (!WaitForDelay()) + if (!WaitForDelay(lock)) break; bool success; @@ -448,7 +448,7 @@ AudioOutputControl::Task() noexcept break; } - InternalPause(); + InternalPause(lock); /* don't "break" here: this might cause Play() to be called when command==CLOSE ends the paused state - "continue" checks @@ -472,7 +472,7 @@ AudioOutputControl::Task() noexcept have been invalidated by stopping the actual playback */ source.Cancel(); - InternalPause(); + InternalPause(lock); } else { InternalClose(false); CommandFinished(); @@ -509,7 +509,7 @@ AudioOutputControl::Task() noexcept return; } - if (open && allow_play && InternalPlay()) + if (open && allow_play && InternalPlay(lock)) /* don't wait for an event if there are more chunks in the pipe */ continue;