OutputThread: use class ScopeUnlock for exception-safety

This commit is contained in:
Max Kellermann 2016-10-28 20:41:53 +02:00
parent 69de99636f
commit f39823eac0

View File

@ -51,9 +51,8 @@ AudioOutput::CommandFinished()
assert(command != Command::NONE); assert(command != Command::NONE);
command = Command::NONE; command = Command::NONE;
mutex.unlock(); const ScopeUnlock unlock(mutex);
audio_output_client_notify.Signal(); audio_output_client_notify.Signal();
mutex.lock();
} }
inline bool inline bool
@ -62,15 +61,15 @@ AudioOutput::Enable()
if (really_enabled) if (really_enabled)
return true; return true;
mutex.unlock(); {
Error error; const ScopeUnlock unlock(mutex);
bool success = ao_plugin_enable(this, error); Error error;
mutex.lock(); if (!ao_plugin_enable(this, error)) {
if (!success) { FormatError(error,
FormatError(error, "Failed to enable \"%s\" [%s]",
"Failed to enable \"%s\" [%s]", name, plugin.name);
name, plugin.name); return false;
return false; }
} }
really_enabled = true; really_enabled = true;
@ -86,9 +85,8 @@ AudioOutput::Disable()
if (really_enabled) { if (really_enabled) {
really_enabled = false; really_enabled = false;
mutex.unlock(); const ScopeUnlock unlock(mutex);
ao_plugin_disable(this); ao_plugin_disable(this);
mutex.lock();
} }
} }
@ -185,9 +183,10 @@ AudioOutput::Open()
FormatError(error, "Failed to open \"%s\" [%s]", FormatError(error, "Failed to open \"%s\" [%s]",
name, plugin.name); name, plugin.name);
mutex.unlock(); {
CloseFilter(); const ScopeUnlock unlock(mutex);
mutex.lock(); CloseFilter();
}
fail_timer.Update(); fail_timer.Update();
return; return;
@ -256,13 +255,11 @@ AudioOutput::Close(bool drain)
current_chunk = nullptr; current_chunk = nullptr;
open = false; open = false;
mutex.unlock(); const ScopeUnlock unlock(mutex);
CloseOutput(drain); CloseOutput(drain);
CloseFilter(); CloseFilter();
mutex.lock();
FormatDebug(output_domain, "closed plugin=%s name=\"%s\"", FormatDebug(output_domain, "closed plugin=%s name=\"%s\"",
plugin.name, name); plugin.name, name);
} }
@ -283,9 +280,10 @@ AudioOutput::ReopenFilter()
{ {
Error error; Error error;
mutex.unlock(); {
CloseFilter(); const ScopeUnlock unlock(mutex);
mutex.lock(); CloseFilter();
}
AudioFormat filter_audio_format; AudioFormat filter_audio_format;
try { try {
@ -458,9 +456,8 @@ AudioOutput::PlayChunk(const MusicChunk *chunk)
assert(filter_instance != nullptr); assert(filter_instance != nullptr);
if (tags && gcc_unlikely(chunk->tag != nullptr)) { if (tags && gcc_unlikely(chunk->tag != nullptr)) {
mutex.unlock(); const ScopeUnlock unlock(mutex);
ao_plugin_send_tag(this, *chunk->tag); ao_plugin_send_tag(this, *chunk->tag);
mutex.lock();
} }
auto data = ConstBuffer<char>::FromVoid(ao_filter_chunk(this, chunk)); auto data = ConstBuffer<char>::FromVoid(ao_filter_chunk(this, chunk));
@ -479,10 +476,14 @@ AudioOutput::PlayChunk(const MusicChunk *chunk)
if (!WaitForDelay()) if (!WaitForDelay())
break; break;
mutex.unlock(); size_t nbytes;
size_t nbytes = ao_plugin_play(this, data.data, data.size,
error); {
mutex.lock(); const ScopeUnlock unlock(mutex);
nbytes = ao_plugin_play(this, data.data, data.size,
error);
}
if (nbytes == 0) { if (nbytes == 0) {
/* play()==0 means failure */ /* play()==0 means failure */
FormatError(error, "\"%s\" [%s] failed to play", FormatError(error, "\"%s\" [%s] failed to play",
@ -552,9 +553,8 @@ AudioOutput::Play()
current_chunk_finished = true; current_chunk_finished = true;
mutex.unlock(); const ScopeUnlock unlock(mutex);
player_control->LockSignal(); player_control->LockSignal();
mutex.lock();
return true; return true;
} }
@ -562,9 +562,10 @@ AudioOutput::Play()
inline void inline void
AudioOutput::Pause() AudioOutput::Pause()
{ {
mutex.unlock(); {
ao_plugin_cancel(this); const ScopeUnlock unlock(mutex);
mutex.lock(); ao_plugin_cancel(this);
}
pause = true; pause = true;
CommandFinished(); CommandFinished();
@ -573,9 +574,11 @@ AudioOutput::Pause()
if (!WaitForDelay()) if (!WaitForDelay())
break; break;
mutex.unlock(); bool success;
bool success = ao_plugin_pause(this); {
mutex.lock(); const ScopeUnlock unlock(mutex);
success = ao_plugin_pause(this);
}
if (!success) { if (!success) {
Close(false); Close(false);
@ -600,7 +603,7 @@ AudioOutput::Task()
SetThreadTimerSlackUS(100); SetThreadTimerSlackUS(100);
mutex.lock(); const ScopeLock lock(mutex);
while (1) { while (1) {
switch (command) { switch (command) {
@ -657,9 +660,8 @@ AudioOutput::Task()
assert(current_chunk == nullptr); assert(current_chunk == nullptr);
assert(pipe->Peek() == nullptr); assert(pipe->Peek() == nullptr);
mutex.unlock(); const ScopeUnlock unlock(mutex);
ao_plugin_drain(this); ao_plugin_drain(this);
mutex.lock();
} }
CommandFinished(); CommandFinished();
@ -669,9 +671,8 @@ AudioOutput::Task()
current_chunk = nullptr; current_chunk = nullptr;
if (open) { if (open) {
mutex.unlock(); const ScopeUnlock unlock(mutex);
ao_plugin_cancel(this); ao_plugin_cancel(this);
mutex.lock();
} }
CommandFinished(); CommandFinished();
@ -680,7 +681,6 @@ AudioOutput::Task()
case Command::KILL: case Command::KILL:
current_chunk = nullptr; current_chunk = nullptr;
CommandFinished(); CommandFinished();
mutex.unlock();
return; return;
} }