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:
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user