decoder_control: protect command, state with a mutex

Replace decoder_control.notify with decoder_control.mutex and
decoder_control.cond.  Lock the mutex on all accesses to
decoder_control.command and decoder_control.state.
This commit is contained in:
Max Kellermann
2009-08-13 23:33:46 +02:00
parent 499ed62dd7
commit e28a0e97b5
6 changed files with 242 additions and 32 deletions

View File

@@ -22,13 +22,16 @@
#include "decoder_command.h"
#include "audio_format.h"
#include "notify.h"
#include <glib.h>
#include <assert.h>
#define DECODE_TYPE_FILE 0
#define DECODE_TYPE_URL 1
struct notify;
enum decoder_state {
DECODE_STATE_STOP = 0,
DECODE_STATE_START,
@@ -48,14 +51,25 @@ struct decoder_control {
thread isn't running */
GThread *thread;
struct notify notify;
/**
* This lock protects #state and #command.
*/
GMutex *mutex;
/**
* Trigger this object after you have modified #command. This
* is also used by the decoder thread to notify the caller
* when it has finished a command.
*/
GCond *cond;
enum decoder_state state;
enum decoder_command command;
volatile enum decoder_state state;
volatile enum decoder_command command;
bool quit;
bool seek_error;
bool seekable;
volatile double seek_where;
double seek_where;
/** the format of the song file */
struct audio_format in_audio_format;
@@ -80,6 +94,46 @@ void dc_init(void);
void dc_deinit(void);
/**
* Locks the #decoder_control object.
*/
static inline void
decoder_lock(void)
{
g_mutex_lock(dc.mutex);
}
/**
* Unlocks the #decoder_control object.
*/
static inline void
decoder_unlock(void)
{
g_mutex_unlock(dc.mutex);
}
/**
* Waits for a signal on the #decoder_control object. This function
* is only valid in the decoder thread. The object must be locked
* prior to calling this function.
*/
static inline void
decoder_wait(void)
{
g_cond_wait(dc.cond, dc.mutex);
}
/**
* Signals the #decoder_control object. This function is only valid
* in the player thread. The object should be locked prior to calling
* this function.
*/
static inline void
decoder_signal(void)
{
g_cond_signal(dc.cond);
}
static inline bool decoder_is_idle(void)
{
return (dc.state == DECODE_STATE_STOP ||
@@ -100,6 +154,39 @@ static inline bool decoder_has_failed(void)
return dc.state == DECODE_STATE_ERROR;
}
static inline bool decoder_lock_is_idle(void)
{
bool ret;
decoder_lock();
ret = decoder_is_idle();
decoder_unlock();
return ret;
}
static inline bool decoder_lock_is_starting(void)
{
bool ret;
decoder_lock();
ret = decoder_is_starting();
decoder_unlock();
return ret;
}
static inline bool decoder_lock_has_failed(void)
{
bool ret;
decoder_lock();
ret = decoder_has_failed();
decoder_unlock();
return ret;
}
static inline struct song *
decoder_current_song(void)
{