output/Control: pass std::unique_lock<> to Cond::wait()

This commit is contained in:
Max Kellermann 2019-04-26 18:24:26 +02:00
parent 4473816384
commit 23d56cb6a1
3 changed files with 41 additions and 38 deletions

View File

@ -112,10 +112,10 @@ AudioOutputControl::LockToggleEnabled() noexcept
} }
void void
AudioOutputControl::WaitForCommand() noexcept AudioOutputControl::WaitForCommand(std::unique_lock<Mutex> &lock) noexcept
{ {
while (!IsCommandFinished()) while (!IsCommandFinished())
client_cond.wait(mutex); client_cond.wait(lock);
} }
void void
@ -128,17 +128,18 @@ AudioOutputControl::CommandAsync(Command cmd) noexcept
} }
void void
AudioOutputControl::CommandWait(Command cmd) noexcept AudioOutputControl::CommandWait(std::unique_lock<Mutex> &lock,
Command cmd) noexcept
{ {
CommandAsync(cmd); CommandAsync(cmd);
WaitForCommand(); WaitForCommand(lock);
} }
void void
AudioOutputControl::LockCommandWait(Command cmd) noexcept AudioOutputControl::LockCommandWait(Command cmd) noexcept
{ {
const std::lock_guard<Mutex> protect(mutex); std::unique_lock<Mutex> lock(mutex);
CommandWait(cmd); CommandWait(lock, cmd);
} }
void void
@ -189,7 +190,8 @@ AudioOutputControl::EnableDisableAsync()
} }
inline bool inline bool
AudioOutputControl::Open(const AudioFormat audio_format, AudioOutputControl::Open(std::unique_lock<Mutex> &lock,
const AudioFormat audio_format,
const MusicPipe &mp) noexcept const MusicPipe &mp) noexcept
{ {
assert(allow_play); assert(allow_play);
@ -218,7 +220,7 @@ AudioOutputControl::Open(const AudioFormat audio_format,
} }
} }
CommandWait(Command::OPEN); CommandWait(lock, Command::OPEN);
const bool open2 = open; const bool open2 = open;
if (open2 && output->mixer != nullptr) { if (open2 && output->mixer != nullptr) {
@ -236,7 +238,7 @@ AudioOutputControl::Open(const AudioFormat audio_format,
} }
void void
AudioOutputControl::CloseWait() noexcept AudioOutputControl::CloseWait(std::unique_lock<Mutex> &lock) noexcept
{ {
assert(allow_play); assert(allow_play);
@ -246,7 +248,7 @@ AudioOutputControl::CloseWait() noexcept
assert(!open || !fail_timer.IsDefined()); assert(!open || !fail_timer.IsDefined());
if (open) if (open)
CommandWait(Command::CLOSE); CommandWait(lock, Command::CLOSE);
else else
fail_timer.Reset(); fail_timer.Reset();
} }
@ -256,15 +258,15 @@ AudioOutputControl::LockUpdate(const AudioFormat audio_format,
const MusicPipe &mp, const MusicPipe &mp,
bool force) noexcept bool force) noexcept
{ {
const std::lock_guard<Mutex> protect(mutex); std::unique_lock<Mutex> lock(mutex);
if (enabled && really_enabled) { if (enabled && really_enabled) {
if (force || !fail_timer.IsDefined() || if (force || !fail_timer.IsDefined() ||
fail_timer.Check(REOPEN_AFTER * 1000)) { fail_timer.Check(REOPEN_AFTER * 1000)) {
return Open(audio_format, mp); return Open(lock, audio_format, mp);
} }
} else if (IsOpen()) } else if (IsOpen())
CloseWait(); CloseWait(lock);
return false; return false;
} }
@ -355,13 +357,13 @@ AudioOutputControl::LockRelease() noexcept
mixer_auto_close()) */ mixer_auto_close()) */
mixer_auto_close(output->mixer); mixer_auto_close(output->mixer);
const std::lock_guard<Mutex> protect(mutex); std::unique_lock<Mutex> lock(mutex);
assert(!open || !fail_timer.IsDefined()); assert(!open || !fail_timer.IsDefined());
assert(allow_play); assert(allow_play);
if (IsOpen()) if (IsOpen())
CommandWait(Command::RELEASE); CommandWait(lock, Command::RELEASE);
else else
fail_timer.Reset(); fail_timer.Reset();
} }
@ -371,8 +373,8 @@ AudioOutputControl::LockCloseWait() noexcept
{ {
assert(!open || !fail_timer.IsDefined()); assert(!open || !fail_timer.IsDefined());
const std::lock_guard<Mutex> protect(mutex); std::unique_lock<Mutex> lock(mutex);
CloseWait(); CloseWait(lock);
} }
void void

View File

@ -307,11 +307,11 @@ public:
* *
* Caller must lock the mutex. * Caller must lock the mutex.
*/ */
void WaitForCommand() noexcept; void WaitForCommand(std::unique_lock<Mutex> &lock) noexcept;
void LockWaitForCommand() noexcept { void LockWaitForCommand() noexcept {
const std::lock_guard<Mutex> protect(mutex); std::unique_lock<Mutex> lock(mutex);
WaitForCommand(); WaitForCommand(lock);
} }
/** /**
@ -326,7 +326,7 @@ public:
* *
* Caller must lock the mutex. * Caller must lock the mutex.
*/ */
void CommandWait(Command cmd) noexcept; void CommandWait(std::unique_lock<Mutex> &lock, Command cmd) noexcept;
/** /**
* Lock the object and execute the command synchronously. * Lock the object and execute the command synchronously.
@ -368,7 +368,7 @@ public:
void LockPauseAsync() noexcept; void LockPauseAsync() noexcept;
void CloseWait() noexcept; void CloseWait(std::unique_lock<Mutex> &lock) noexcept;
void LockCloseWait() noexcept; void LockCloseWait() noexcept;
/** /**
@ -391,7 +391,8 @@ public:
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.
*/ */
bool Open(AudioFormat audio_format, const MusicPipe &mp) noexcept; bool Open(std::unique_lock<Mutex> &lock,
AudioFormat audio_format, const MusicPipe &mp) noexcept;
/** /**
* Opens or closes the device, depending on the "enabled" * Opens or closes the device, depending on the "enabled"
@ -522,7 +523,7 @@ private:
* @return true if playback should be continued, false if a * @return true if playback should be continued, false if a
* command was issued * command was issued
*/ */
bool WaitForDelay() noexcept; bool WaitForDelay(std::unique_lock<Mutex> &lock) noexcept;
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.
@ -532,7 +533,7 @@ private:
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.
*/ */
bool PlayChunk() noexcept; bool PlayChunk(std::unique_lock<Mutex> &lock) noexcept;
/** /**
* Plays all remaining chunks, until the tail of the pipe has * 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, * @return true if at least one chunk has been available,
* false if the tail of the pipe was already reached * false if the tail of the pipe was already reached
*/ */
bool InternalPlay() noexcept; bool InternalPlay(std::unique_lock<Mutex> &lock) noexcept;
/** /**
* Runs inside the OutputThread. * Runs inside the OutputThread.
* Caller must lock the mutex. * Caller must lock the mutex.
* Handles exceptions. * Handles exceptions.
*/ */
void InternalPause() noexcept; void InternalPause(std::unique_lock<Mutex> &lock) noexcept;
/** /**
* Runs inside the OutputThread. * Runs inside the OutputThread.

View File

@ -208,14 +208,14 @@ AudioOutputControl::InternalCheckClose(bool drain) noexcept
* was issued * was issued
*/ */
inline bool inline bool
AudioOutputControl::WaitForDelay() noexcept AudioOutputControl::WaitForDelay(std::unique_lock<Mutex> &lock) noexcept
{ {
while (true) { while (true) {
const auto delay = output->Delay(); const auto delay = output->Delay();
if (delay <= std::chrono::steady_clock::duration::zero()) if (delay <= std::chrono::steady_clock::duration::zero())
return true; return true;
(void)wake_cond.wait_for(mutex, delay); (void)wake_cond.wait_for(lock, delay);
if (command != Command::NONE) if (command != Command::NONE)
return false; return false;
@ -234,7 +234,7 @@ try {
} }
inline bool inline bool
AudioOutputControl::PlayChunk() noexcept AudioOutputControl::PlayChunk(std::unique_lock<Mutex> &lock) noexcept
{ {
// ensure pending tags are flushed in all cases // ensure pending tags are flushed in all cases
const auto *tag = source.ReadTag(); const auto *tag = source.ReadTag();
@ -256,7 +256,7 @@ AudioOutputControl::PlayChunk() noexcept
if (skip_delay) if (skip_delay)
skip_delay = false; skip_delay = false;
else if (!WaitForDelay()) else if (!WaitForDelay(lock))
break; break;
size_t nbytes; size_t nbytes;
@ -282,7 +282,7 @@ AudioOutputControl::PlayChunk() noexcept
} }
inline bool inline bool
AudioOutputControl::InternalPlay() noexcept AudioOutputControl::InternalPlay(std::unique_lock<Mutex> &lock) noexcept
{ {
if (!FillSourceOrClose()) if (!FillSourceOrClose())
/* no chunk available */ /* no chunk available */
@ -311,7 +311,7 @@ AudioOutputControl::InternalPlay() noexcept
n = 0; n = 0;
} }
if (!PlayChunk()) if (!PlayChunk(lock))
break; break;
} while (FillSourceOrClose()); } while (FillSourceOrClose());
@ -322,7 +322,7 @@ AudioOutputControl::InternalPlay() noexcept
} }
inline void inline void
AudioOutputControl::InternalPause() noexcept AudioOutputControl::InternalPause(std::unique_lock<Mutex> &lock) noexcept
{ {
{ {
const ScopeUnlock unlock(mutex); const ScopeUnlock unlock(mutex);
@ -334,7 +334,7 @@ AudioOutputControl::InternalPause() noexcept
CommandFinished(); CommandFinished();
do { do {
if (!WaitForDelay()) if (!WaitForDelay(lock))
break; break;
bool success; bool success;
@ -448,7 +448,7 @@ AudioOutputControl::Task() noexcept
break; break;
} }
InternalPause(); InternalPause(lock);
/* don't "break" here: this might cause /* don't "break" here: this might cause
Play() to be called when command==CLOSE Play() to be called when command==CLOSE
ends the paused state - "continue" checks ends the paused state - "continue" checks
@ -472,7 +472,7 @@ AudioOutputControl::Task() noexcept
have been invalidated by stopping have been invalidated by stopping
the actual playback */ the actual playback */
source.Cancel(); source.Cancel();
InternalPause(); InternalPause(lock);
} else { } else {
InternalClose(false); InternalClose(false);
CommandFinished(); CommandFinished();
@ -509,7 +509,7 @@ AudioOutputControl::Task() noexcept
return; return;
} }
if (open && allow_play && InternalPlay()) if (open && allow_play && InternalPlay(lock))
/* don't wait for an event if there are more /* don't wait for an event if there are more
chunks in the pipe */ chunks in the pipe */
continue; continue;