OutputInternal: use Mutex instead of GMutex

This commit is contained in:
Max Kellermann 2013-04-17 01:19:25 +02:00
parent c5c43c4541
commit a28df6123f
6 changed files with 62 additions and 89 deletions

View File

@ -161,9 +161,9 @@ audio_output_all_enable_disable(void)
struct audio_output *ao = audio_outputs[i]; struct audio_output *ao = audio_outputs[i];
bool enabled; bool enabled;
g_mutex_lock(ao->mutex); ao->mutex.lock();
enabled = ao->really_enabled; enabled = ao->really_enabled;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
if (ao->enabled != enabled) { if (ao->enabled != enabled) {
if (ao->enabled) if (ao->enabled)
@ -183,14 +183,10 @@ audio_output_all_finished(void)
{ {
for (unsigned i = 0; i < num_audio_outputs; ++i) { for (unsigned i = 0; i < num_audio_outputs; ++i) {
struct audio_output *ao = audio_outputs[i]; struct audio_output *ao = audio_outputs[i];
bool not_finished;
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
not_finished = audio_output_is_open(ao) && if (audio_output_is_open(ao) &&
!audio_output_command_is_finished(ao); !audio_output_command_is_finished(ao))
g_mutex_unlock(ao->mutex);
if (not_finished)
return false; return false;
} }
@ -216,14 +212,12 @@ audio_output_allow_play_all(void)
static void static void
audio_output_reset_reopen(struct audio_output *ao) audio_output_reset_reopen(struct audio_output *ao)
{ {
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
if (!ao->open && ao->fail_timer != NULL) { if (!ao->open && ao->fail_timer != NULL) {
g_timer_destroy(ao->fail_timer); g_timer_destroy(ao->fail_timer);
ao->fail_timer = NULL; ao->fail_timer = NULL;
} }
g_mutex_unlock(ao->mutex);
} }
/** /**
@ -383,14 +377,10 @@ static bool
chunk_is_consumed(const struct music_chunk *chunk) chunk_is_consumed(const struct music_chunk *chunk)
{ {
for (unsigned i = 0; i < num_audio_outputs; ++i) { for (unsigned i = 0; i < num_audio_outputs; ++i) {
const struct audio_output *ao = audio_outputs[i]; struct audio_output *ao = audio_outputs[i];
bool consumed;
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
consumed = chunk_is_consumed_in(ao, chunk); if (!chunk_is_consumed_in(ao, chunk))
g_mutex_unlock(ao->mutex);
if (!consumed)
return false; return false;
} }
@ -412,11 +402,11 @@ clear_tail_chunk(G_GNUC_UNUSED const struct music_chunk *chunk, bool *locked)
/* this mutex will be unlocked by the caller when it's /* this mutex will be unlocked by the caller when it's
ready */ ready */
g_mutex_lock(ao->mutex); ao->mutex.lock();
locked[i] = ao->open; locked[i] = ao->open;
if (!locked[i]) { if (!locked[i]) {
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
continue; continue;
} }
@ -465,7 +455,7 @@ audio_output_all_check(void)
by clear_tail_chunk() */ by clear_tail_chunk() */
for (unsigned i = 0; i < num_audio_outputs; ++i) for (unsigned i = 0; i < num_audio_outputs; ++i)
if (locked[i]) if (locked[i])
g_mutex_unlock(audio_outputs[i]->mutex); audio_outputs[i]->mutex.unlock();
/* return the chunk to the buffer */ /* return the chunk to the buffer */
music_buffer_return(g_music_buffer, shifted); music_buffer_return(g_music_buffer, shifted);

View File

@ -47,9 +47,9 @@ struct notify audio_output_client_notify;
static void ao_command_wait(struct audio_output *ao) static void ao_command_wait(struct audio_output *ao)
{ {
while (ao->command != AO_COMMAND_NONE) { while (ao->command != AO_COMMAND_NONE) {
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
audio_output_client_notify.Wait(); audio_output_client_notify.Wait();
g_mutex_lock(ao->mutex); ao->mutex.lock();
} }
} }
@ -64,7 +64,7 @@ static void ao_command_async(struct audio_output *ao,
{ {
assert(ao->command == AO_COMMAND_NONE); assert(ao->command == AO_COMMAND_NONE);
ao->command = cmd; ao->command = cmd;
g_cond_signal(ao->cond); ao->cond.signal();
} }
/** /**
@ -87,9 +87,8 @@ ao_command(struct audio_output *ao, enum audio_output_command cmd)
static void static void
ao_lock_command(struct audio_output *ao, enum audio_output_command cmd) ao_lock_command(struct audio_output *ao, enum audio_output_command cmd)
{ {
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
ao_command(ao, cmd); ao_command(ao, cmd);
g_mutex_unlock(ao->mutex);
} }
void void
@ -231,33 +230,28 @@ audio_output_update(struct audio_output *ao,
{ {
assert(mp != NULL); assert(mp != NULL);
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
if (ao->enabled && ao->really_enabled) { if (ao->enabled && ao->really_enabled) {
if (ao->fail_timer == NULL || if (ao->fail_timer == NULL ||
g_timer_elapsed(ao->fail_timer, NULL) > REOPEN_AFTER) { g_timer_elapsed(ao->fail_timer, NULL) > REOPEN_AFTER) {
bool success = audio_output_open(ao, audio_format, mp); return audio_output_open(ao, audio_format, mp);
g_mutex_unlock(ao->mutex);
return success;
} }
} else if (audio_output_is_open(ao)) } else if (audio_output_is_open(ao))
audio_output_close_locked(ao); audio_output_close_locked(ao);
g_mutex_unlock(ao->mutex);
return false; return false;
} }
void void
audio_output_play(struct audio_output *ao) audio_output_play(struct audio_output *ao)
{ {
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
assert(ao->allow_play); assert(ao->allow_play);
if (audio_output_is_open(ao)) if (audio_output_is_open(ao))
g_cond_signal(ao->cond); ao->cond.signal();
g_mutex_unlock(ao->mutex);
} }
void audio_output_pause(struct audio_output *ao) void audio_output_pause(struct audio_output *ao)
@ -268,45 +262,41 @@ void audio_output_pause(struct audio_output *ao)
mixer_auto_close()) */ mixer_auto_close()) */
mixer_auto_close(ao->mixer); mixer_auto_close(ao->mixer);
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
assert(ao->allow_play); assert(ao->allow_play);
if (audio_output_is_open(ao)) if (audio_output_is_open(ao))
ao_command_async(ao, AO_COMMAND_PAUSE); ao_command_async(ao, AO_COMMAND_PAUSE);
g_mutex_unlock(ao->mutex);
} }
void void
audio_output_drain_async(struct audio_output *ao) audio_output_drain_async(struct audio_output *ao)
{ {
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
assert(ao->allow_play); assert(ao->allow_play);
if (audio_output_is_open(ao)) if (audio_output_is_open(ao))
ao_command_async(ao, AO_COMMAND_DRAIN); ao_command_async(ao, AO_COMMAND_DRAIN);
g_mutex_unlock(ao->mutex);
} }
void audio_output_cancel(struct audio_output *ao) void audio_output_cancel(struct audio_output *ao)
{ {
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
if (audio_output_is_open(ao)) { if (audio_output_is_open(ao)) {
ao->allow_play = false; ao->allow_play = false;
ao_command_async(ao, AO_COMMAND_CANCEL); ao_command_async(ao, AO_COMMAND_CANCEL);
} }
g_mutex_unlock(ao->mutex);
} }
void void
audio_output_allow_play(struct audio_output *ao) audio_output_allow_play(struct audio_output *ao)
{ {
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
ao->allow_play = true; ao->allow_play = true;
if (audio_output_is_open(ao)) if (audio_output_is_open(ao))
g_cond_signal(ao->cond); ao->cond.signal();
g_mutex_unlock(ao->mutex);
} }
void void
@ -323,9 +313,8 @@ void audio_output_close(struct audio_output *ao)
assert(ao != NULL); assert(ao != NULL);
assert(!ao->open || ao->fail_timer == NULL); assert(!ao->open || ao->fail_timer == NULL);
g_mutex_lock(ao->mutex); const ScopeLock protect(ao->mutex);
audio_output_close_locked(ao); audio_output_close_locked(ao);
g_mutex_unlock(ao->mutex);
} }
void audio_output_finish(struct audio_output *ao) void audio_output_finish(struct audio_output *ao)

View File

@ -35,9 +35,6 @@ ao_base_finish(struct audio_output *ao)
if (ao->mixer != NULL) if (ao->mixer != NULL)
mixer_free(ao->mixer); mixer_free(ao->mixer);
g_cond_free(ao->cond);
g_mutex_free(ao->mutex);
delete ao->replay_gain_filter; delete ao->replay_gain_filter;
delete ao->other_replay_gain_filter; delete ao->other_replay_gain_filter;
delete ao->filter; delete ao->filter;

View File

@ -209,8 +209,6 @@ ao_base_init(struct audio_output *ao,
ao->thread = NULL; ao->thread = NULL;
ao->command = AO_COMMAND_NONE; ao->command = AO_COMMAND_NONE;
ao->mutex = g_mutex_new();
ao->cond = g_cond_new();
ao->mixer = NULL; ao->mixer = NULL;
ao->replay_gain_filter = NULL; ao->replay_gain_filter = NULL;

View File

@ -22,6 +22,8 @@
#include "audio_format.h" #include "audio_format.h"
#include "pcm/pcm_buffer.h" #include "pcm/pcm_buffer.h"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include <glib.h> #include <glib.h>
@ -212,13 +214,13 @@ struct audio_output {
* This mutex protects #open, #fail_timer, #chunk and * This mutex protects #open, #fail_timer, #chunk and
* #chunk_finished. * #chunk_finished.
*/ */
GMutex *mutex; Mutex mutex;
/** /**
* This condition object wakes up the output thread after * This condition object wakes up the output thread after
* #command has been set. * #command has been set.
*/ */
GCond *cond; Cond cond;
/** /**
* The player_control object which "owns" this output. This * The player_control object which "owns" this output. This

View File

@ -47,9 +47,9 @@ static void ao_command_finished(struct audio_output *ao)
assert(ao->command != AO_COMMAND_NONE); assert(ao->command != AO_COMMAND_NONE);
ao->command = AO_COMMAND_NONE; ao->command = AO_COMMAND_NONE;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
audio_output_client_notify.Signal(); audio_output_client_notify.Signal();
g_mutex_lock(ao->mutex); ao->mutex.lock();
} }
static bool static bool
@ -61,9 +61,9 @@ ao_enable(struct audio_output *ao)
if (ao->really_enabled) if (ao->really_enabled)
return true; return true;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
success = ao_plugin_enable(ao, &error); success = ao_plugin_enable(ao, &error);
g_mutex_lock(ao->mutex); ao->mutex.lock();
if (!success) { if (!success) {
g_warning("Failed to enable \"%s\" [%s]: %s\n", g_warning("Failed to enable \"%s\" [%s]: %s\n",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error->message);
@ -87,9 +87,9 @@ ao_disable(struct audio_output *ao)
if (ao->really_enabled) { if (ao->really_enabled) {
ao->really_enabled = false; ao->really_enabled = false;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
ao_plugin_disable(ao); ao_plugin_disable(ao);
g_mutex_lock(ao->mutex); ao->mutex.lock();
} }
} }
@ -174,9 +174,9 @@ ao_open(struct audio_output *ao)
audio_format_mask_apply(&ao->out_audio_format, audio_format_mask_apply(&ao->out_audio_format,
&ao->config_audio_format); &ao->config_audio_format);
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
success = ao_plugin_open(ao, &ao->out_audio_format, &error); success = ao_plugin_open(ao, &ao->out_audio_format, &error);
g_mutex_lock(ao->mutex); ao->mutex.lock();
assert(!ao->open); assert(!ao->open);
@ -216,7 +216,7 @@ ao_close(struct audio_output *ao, bool drain)
ao->chunk = NULL; ao->chunk = NULL;
ao->open = false; ao->open = false;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
if (drain) if (drain)
ao_plugin_drain(ao); ao_plugin_drain(ao);
@ -226,7 +226,7 @@ ao_close(struct audio_output *ao, bool drain)
ao_plugin_close(ao); ao_plugin_close(ao);
ao_filter_close(ao); ao_filter_close(ao);
g_mutex_lock(ao->mutex); ao->mutex.lock();
g_debug("closed plugin=%s name=\"%s\"", ao->plugin->name, ao->name); g_debug("closed plugin=%s name=\"%s\"", ao->plugin->name, ao->name);
} }
@ -254,9 +254,9 @@ ao_reopen_filter(struct audio_output *ao)
ao->open = false; ao->open = false;
ao->fail_timer = g_timer_new(); ao->fail_timer = g_timer_new();
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
ao_plugin_close(ao); ao_plugin_close(ao);
g_mutex_lock(ao->mutex); ao->mutex.lock();
return; return;
} }
@ -304,10 +304,7 @@ ao_wait(struct audio_output *ao)
if (delay == 0) if (delay == 0)
return true; return true;
GTimeVal tv; (void)ao->cond.timed_wait(ao->mutex, delay);
g_get_current_time(&tv);
g_time_val_add(&tv, delay * 1000);
(void)g_cond_timed_wait(ao->cond, ao->mutex, &tv);
if (ao->command != AO_COMMAND_NONE) if (ao->command != AO_COMMAND_NONE)
return false; return false;
@ -436,9 +433,9 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
assert(ao->filter != NULL); assert(ao->filter != NULL);
if (ao->tags && gcc_unlikely(chunk->tag != NULL)) { if (ao->tags && gcc_unlikely(chunk->tag != NULL)) {
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
ao_plugin_send_tag(ao, chunk->tag); ao_plugin_send_tag(ao, chunk->tag);
g_mutex_lock(ao->mutex); ao->mutex.lock();
} }
size_t size; size_t size;
@ -462,9 +459,9 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
if (!ao_wait(ao)) if (!ao_wait(ao))
break; break;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
nbytes = ao_plugin_play(ao, data, size, &error); nbytes = ao_plugin_play(ao, data, size, &error);
g_mutex_lock(ao->mutex); ao->mutex.lock();
if (nbytes == 0) { if (nbytes == 0) {
/* play()==0 means failure */ /* play()==0 means failure */
g_warning("\"%s\" [%s] failed to play: %s", g_warning("\"%s\" [%s] failed to play: %s",
@ -541,9 +538,9 @@ ao_play(struct audio_output *ao)
ao->chunk_finished = true; ao->chunk_finished = true;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
ao->player_control->LockSignal(); ao->player_control->LockSignal();
g_mutex_lock(ao->mutex); ao->mutex.lock();
return true; return true;
} }
@ -552,9 +549,9 @@ static void ao_pause(struct audio_output *ao)
{ {
bool ret; bool ret;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
ao_plugin_cancel(ao); ao_plugin_cancel(ao);
g_mutex_lock(ao->mutex); ao->mutex.lock();
ao->pause = true; ao->pause = true;
ao_command_finished(ao); ao_command_finished(ao);
@ -563,9 +560,9 @@ static void ao_pause(struct audio_output *ao)
if (!ao_wait(ao)) if (!ao_wait(ao))
break; break;
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
ret = ao_plugin_pause(ao); ret = ao_plugin_pause(ao);
g_mutex_lock(ao->mutex); ao->mutex.lock();
if (!ret) { if (!ret) {
ao_close(ao, false); ao_close(ao, false);
@ -580,7 +577,7 @@ static gpointer audio_output_task(gpointer arg)
{ {
struct audio_output *ao = (struct audio_output *)arg; struct audio_output *ao = (struct audio_output *)arg;
g_mutex_lock(ao->mutex); ao->mutex.lock();
while (1) { while (1) {
switch (ao->command) { switch (ao->command) {
@ -637,9 +634,9 @@ static gpointer audio_output_task(gpointer arg)
assert(ao->chunk == NULL); assert(ao->chunk == NULL);
assert(music_pipe_peek(ao->pipe) == NULL); assert(music_pipe_peek(ao->pipe) == NULL);
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
ao_plugin_drain(ao); ao_plugin_drain(ao);
g_mutex_lock(ao->mutex); ao->mutex.lock();
} }
ao_command_finished(ao); ao_command_finished(ao);
@ -649,9 +646,9 @@ static gpointer audio_output_task(gpointer arg)
ao->chunk = NULL; ao->chunk = NULL;
if (ao->open) { if (ao->open) {
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
ao_plugin_cancel(ao); ao_plugin_cancel(ao);
g_mutex_lock(ao->mutex); ao->mutex.lock();
} }
ao_command_finished(ao); ao_command_finished(ao);
@ -660,7 +657,7 @@ static gpointer audio_output_task(gpointer arg)
case AO_COMMAND_KILL: case AO_COMMAND_KILL:
ao->chunk = NULL; ao->chunk = NULL;
ao_command_finished(ao); ao_command_finished(ao);
g_mutex_unlock(ao->mutex); ao->mutex.unlock();
return NULL; return NULL;
} }
@ -670,7 +667,7 @@ static gpointer audio_output_task(gpointer arg)
continue; continue;
if (ao->command == AO_COMMAND_NONE) if (ao->command == AO_COMMAND_NONE)
g_cond_wait(ao->cond, ao->mutex); ao->cond.wait(ao->mutex);
} }
} }