Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
8e676db6
Commit
8e676db6
authored
Oct 17, 2013
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Thread/Thread: replacement library for GThread
parent
f6d74012
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
310 additions
and
98 deletions
+310
-98
Makefile.am
Makefile.am
+9
-0
ClientNew.cxx
src/ClientNew.cxx
+2
-0
DecoderControl.cxx
src/DecoderControl.cxx
+3
-5
DecoderControl.hxx
src/DecoderControl.hxx
+5
-4
DecoderThread.cxx
src/DecoderThread.cxx
+6
-13
IOThread.cxx
src/IOThread.cxx
+12
-19
OutputAll.cxx
src/OutputAll.cxx
+2
-0
OutputControl.cxx
src/OutputControl.cxx
+5
-6
OutputFinish.cxx
src/OutputFinish.cxx
+2
-2
OutputInit.cxx
src/OutputInit.cxx
+0
-1
OutputInternal.hxx
src/OutputInternal.hxx
+2
-2
OutputThread.cxx
src/OutputThread.cxx
+6
-9
PlayerCommands.cxx
src/PlayerCommands.cxx
+2
-0
PlayerControl.cxx
src/PlayerControl.cxx
+4
-4
PlayerControl.hxx
src/PlayerControl.hxx
+8
-8
PlayerThread.cxx
src/PlayerThread.cxx
+8
-13
PlaylistState.cxx
src/PlaylistState.cxx
+2
-0
QueueCommands.cxx
src/QueueCommands.cxx
+2
-0
UpdateGlue.cxx
src/UpdateGlue.cxx
+8
-12
Thread.cxx
src/thread/Thread.cxx
+108
-0
Thread.hxx
src/thread/Thread.hxx
+114
-0
No files found.
Makefile.am
View file @
8e676db6
...
@@ -274,6 +274,7 @@ libthread_a_SOURCES = \
...
@@ -274,6 +274,7 @@ libthread_a_SOURCES = \
src/thread/PosixCond.hxx
\
src/thread/PosixCond.hxx
\
src/thread/WindowsCond.hxx
\
src/thread/WindowsCond.hxx
\
src/thread/GLibCond.hxx
\
src/thread/GLibCond.hxx
\
src/thread/Thread.cxx src/thread/Thread.hxx
\
src/thread/Id.hxx
src/thread/Id.hxx
# System library
# System library
...
@@ -1120,6 +1121,7 @@ test_run_input_LDADD = \
...
@@ -1120,6 +1121,7 @@ test_run_input_LDADD = \
libconf.a
\
libconf.a
\
libutil.a
\
libutil.a
\
libevent.a
\
libevent.a
\
libthread.a
\
libsystem.a
\
libsystem.a
\
libfs.a
\
libfs.a
\
$(GLIB_LIBS)
$(GLIB_LIBS)
...
@@ -1138,6 +1140,7 @@ test_visit_archive_LDADD = \
...
@@ -1138,6 +1140,7 @@ test_visit_archive_LDADD = \
libconf.a
\
libconf.a
\
libutil.a
\
libutil.a
\
libevent.a
\
libevent.a
\
libthread.a
\
libsystem.a
\
libsystem.a
\
libfs.a
\
libfs.a
\
$(GLIB_LIBS)
$(GLIB_LIBS)
...
@@ -1160,6 +1163,7 @@ test_dump_text_file_LDADD = \
...
@@ -1160,6 +1163,7 @@ test_dump_text_file_LDADD = \
libevent.a
\
libevent.a
\
libfs.a
\
libfs.a
\
libsystem.a
\
libsystem.a
\
libthread.a
\
libutil.a
\
libutil.a
\
$(GLIB_LIBS)
$(GLIB_LIBS)
test_dump_text_file_SOURCES
=
test
/dump_text_file.cxx
\
test_dump_text_file_SOURCES
=
test
/dump_text_file.cxx
\
...
@@ -1177,6 +1181,7 @@ test_dump_playlist_LDADD = \
...
@@ -1177,6 +1181,7 @@ test_dump_playlist_LDADD = \
$(TAG_LIBS)
\
$(TAG_LIBS)
\
libconf.a
\
libconf.a
\
libevent.a
\
libevent.a
\
libthread.a
\
libsystem.a
\
libsystem.a
\
libfs.a
\
libfs.a
\
libutil.a
\
libutil.a
\
...
@@ -1206,6 +1211,7 @@ test_run_decoder_LDADD = \
...
@@ -1206,6 +1211,7 @@ test_run_decoder_LDADD = \
$(TAG_LIBS)
\
$(TAG_LIBS)
\
libconf.a
\
libconf.a
\
libevent.a
\
libevent.a
\
libthread.a
\
libsystem.a
\
libsystem.a
\
libfs.a
\
libfs.a
\
libutil.a
\
libutil.a
\
...
@@ -1229,6 +1235,7 @@ test_read_tags_LDADD = \
...
@@ -1229,6 +1235,7 @@ test_read_tags_LDADD = \
$(TAG_LIBS)
\
$(TAG_LIBS)
\
libconf.a
\
libconf.a
\
libevent.a
\
libevent.a
\
libthread.a
\
libsystem.a
\
libsystem.a
\
libfs.a
\
libfs.a
\
libutil.a
\
libutil.a
\
...
@@ -1289,6 +1296,7 @@ test_run_encoder_LDADD = \
...
@@ -1289,6 +1296,7 @@ test_run_encoder_LDADD = \
$(TAG_LIBS)
\
$(TAG_LIBS)
\
libconf.a
\
libconf.a
\
libpcm.a
\
libpcm.a
\
libthread.a
\
libsystem.a
\
libsystem.a
\
libfs.a
\
libfs.a
\
libutil.a
\
libutil.a
\
...
@@ -1356,6 +1364,7 @@ test_run_output_LDADD = $(MPD_LIBS) \
...
@@ -1356,6 +1364,7 @@ test_run_output_LDADD = $(MPD_LIBS) \
libevent.a
\
libevent.a
\
libfs.a
\
libfs.a
\
libsystem.a
\
libsystem.a
\
libthread.a
\
libutil.a
\
libutil.a
\
$(GLIB_LIBS)
$(GLIB_LIBS)
test_run_output_SOURCES
=
test
/run_output.cxx
\
test_run_output_SOURCES
=
test
/run_output.cxx
\
...
...
src/ClientNew.cxx
View file @
8e676db6
...
@@ -28,6 +28,8 @@
...
@@ -28,6 +28,8 @@
#include "util/Error.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
#include "Log.hxx"
#include <glib.h>
#include <assert.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/types.h>
#ifdef WIN32
#ifdef WIN32
...
...
src/DecoderControl.cxx
View file @
8e676db6
...
@@ -27,8 +27,7 @@
...
@@ -27,8 +27,7 @@
#include <assert.h>
#include <assert.h>
decoder_control
::
decoder_control
()
decoder_control
::
decoder_control
()
:
thread
(
nullptr
),
:
state
(
DecoderState
::
STOP
),
state
(
DecoderState
::
STOP
),
command
(
DecoderCommand
::
NONE
),
command
(
DecoderCommand
::
NONE
),
song
(
nullptr
),
song
(
nullptr
),
replay_gain_db
(
0
),
replay_gain_prev_db
(
0
),
replay_gain_db
(
0
),
replay_gain_prev_db
(
0
),
...
@@ -124,13 +123,12 @@ decoder_control::Seek(double where)
...
@@ -124,13 +123,12 @@ decoder_control::Seek(double where)
void
void
decoder_control
::
Quit
()
decoder_control
::
Quit
()
{
{
assert
(
thread
!=
nullptr
);
assert
(
thread
.
IsDefined
()
);
quit
=
true
;
quit
=
true
;
LockAsynchronousCommand
(
DecoderCommand
::
STOP
);
LockAsynchronousCommand
(
DecoderCommand
::
STOP
);
g_thread_join
(
thread
);
thread
.
Join
();
thread
=
nullptr
;
}
}
void
void
...
...
src/DecoderControl.hxx
View file @
8e676db6
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include "AudioFormat.hxx"
#include "AudioFormat.hxx"
#include "thread/Mutex.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "thread/Cond.hxx"
#include "thread/Thread.hxx"
#include "util/Error.hxx"
#include "util/Error.hxx"
#include <assert.h>
#include <assert.h>
...
@@ -37,7 +38,6 @@
...
@@ -37,7 +38,6 @@
struct
Song
;
struct
Song
;
class
MusicBuffer
;
class
MusicBuffer
;
class
MusicPipe
;
class
MusicPipe
;
typedef
struct
_GThread
GThread
;
enum
class
DecoderState
:
uint8_t
{
enum
class
DecoderState
:
uint8_t
{
STOP
=
0
,
STOP
=
0
,
...
@@ -54,9 +54,10 @@ enum class DecoderState : uint8_t {
...
@@ -54,9 +54,10 @@ enum class DecoderState : uint8_t {
};
};
struct
decoder_control
{
struct
decoder_control
{
/** the handle of the decoder thread, or NULL if the decoder
/**
thread isn't running */
* The handle of the decoder thread.
GThread
*
thread
;
*/
Thread
thread
;
/**
/**
* This lock protects #state and #command.
* This lock protects #state and #command.
...
...
src/DecoderThread.cxx
View file @
8e676db6
...
@@ -440,8 +440,8 @@ decoder_run(struct decoder_control *dc)
...
@@ -440,8 +440,8 @@ decoder_run(struct decoder_control *dc)
}
}
static
gpointer
static
void
decoder_task
(
gpointer
arg
)
decoder_task
(
void
*
arg
)
{
{
struct
decoder_control
*
dc
=
(
struct
decoder_control
*
)
arg
;
struct
decoder_control
*
dc
=
(
struct
decoder_control
*
)
arg
;
...
@@ -476,23 +476,16 @@ decoder_task(gpointer arg)
...
@@ -476,23 +476,16 @@ decoder_task(gpointer arg)
}
while
(
dc
->
command
!=
DecoderCommand
::
NONE
||
!
dc
->
quit
);
}
while
(
dc
->
command
!=
DecoderCommand
::
NONE
||
!
dc
->
quit
);
dc
->
Unlock
();
dc
->
Unlock
();
return
NULL
;
}
}
void
void
decoder_thread_start
(
struct
decoder_control
*
dc
)
decoder_thread_start
(
struct
decoder_control
*
dc
)
{
{
assert
(
dc
->
thread
==
NULL
);
assert
(
!
dc
->
thread
.
IsDefined
()
);
dc
->
quit
=
false
;
dc
->
quit
=
false
;
#if GLIB_CHECK_VERSION(2,32,0)
Error
error
;
dc
->
thread
=
g_thread_new
(
"thread"
,
decoder_task
,
dc
);
if
(
!
dc
->
thread
.
Start
(
decoder_task
,
dc
,
error
))
#else
FatalError
(
error
);
GError
*
e
=
NULL
;
dc
->
thread
=
g_thread_create
(
decoder_task
,
dc
,
true
,
&
e
);
if
(
dc
->
thread
==
NULL
)
FatalError
(
"Failed to spawn decoder task"
,
e
);
#endif
}
}
src/IOThread.cxx
View file @
8e676db6
...
@@ -21,10 +21,10 @@
...
@@ -21,10 +21,10 @@
#include "IOThread.hxx"
#include "IOThread.hxx"
#include "thread/Mutex.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "thread/Cond.hxx"
#include "thread/Thread.hxx"
#include "event/Loop.hxx"
#include "event/Loop.hxx"
#include "system/FatalError.hxx"
#include "system/FatalError.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <assert.h>
#include <assert.h>
...
@@ -33,7 +33,7 @@ static struct {
...
@@ -33,7 +33,7 @@ static struct {
Cond
cond
;
Cond
cond
;
EventLoop
*
loop
;
EventLoop
*
loop
;
GThread
*
thread
;
Thread
thread
;
}
io
;
}
io
;
void
void
...
@@ -45,8 +45,8 @@ io_thread_run(void)
...
@@ -45,8 +45,8 @@ io_thread_run(void)
io
.
loop
->
Run
();
io
.
loop
->
Run
();
}
}
static
gpointer
static
void
io_thread_func
(
gcc_unused
gpointer
arg
)
io_thread_func
(
gcc_unused
void
*
arg
)
{
{
/* lock+unlock to synchronize with io_thread_start(), to be
/* lock+unlock to synchronize with io_thread_start(), to be
sure that io.thread is set */
sure that io.thread is set */
...
@@ -54,14 +54,13 @@ io_thread_func(gcc_unused gpointer arg)
...
@@ -54,14 +54,13 @@ io_thread_func(gcc_unused gpointer arg)
io
.
mutex
.
unlock
();
io
.
mutex
.
unlock
();
io_thread_run
();
io_thread_run
();
return
NULL
;
}
}
void
void
io_thread_init
(
void
)
io_thread_init
(
void
)
{
{
assert
(
io
.
loop
==
NULL
);
assert
(
io
.
loop
==
NULL
);
assert
(
io
.
thread
==
NULL
);
assert
(
!
io
.
thread
.
IsDefined
()
);
io
.
loop
=
new
EventLoop
();
io
.
loop
=
new
EventLoop
();
}
}
...
@@ -70,18 +69,13 @@ void
...
@@ -70,18 +69,13 @@ void
io_thread_start
()
io_thread_start
()
{
{
assert
(
io
.
loop
!=
NULL
);
assert
(
io
.
loop
!=
NULL
);
assert
(
io
.
thread
==
NULL
);
assert
(
!
io
.
thread
.
IsDefined
()
);
const
ScopeLock
protect
(
io
.
mutex
);
const
ScopeLock
protect
(
io
.
mutex
);
#if GLIB_CHECK_VERSION(2,32,0)
Error
error
;
io
.
thread
=
g_thread_new
(
"io"
,
io_thread_func
,
nullptr
);
if
(
!
io
.
thread
.
Start
(
io_thread_func
,
nullptr
,
error
))
#else
GError
*
error
=
nullptr
;
io
.
thread
=
g_thread_create
(
io_thread_func
,
NULL
,
true
,
&
error
);
if
(
io
.
thread
==
NULL
)
FatalError
(
error
);
FatalError
(
error
);
#endif
}
}
void
void
...
@@ -95,10 +89,9 @@ io_thread_quit(void)
...
@@ -95,10 +89,9 @@ io_thread_quit(void)
void
void
io_thread_deinit
(
void
)
io_thread_deinit
(
void
)
{
{
if
(
io
.
thread
!=
NULL
)
{
if
(
io
.
thread
.
IsDefined
()
)
{
io_thread_quit
();
io_thread_quit
();
io
.
thread
.
Join
();
g_thread_join
(
io
.
thread
);
}
}
delete
io
.
loop
;
delete
io
.
loop
;
...
@@ -115,5 +108,5 @@ io_thread_get()
...
@@ -115,5 +108,5 @@ io_thread_get()
bool
bool
io_thread_inside
(
void
)
io_thread_inside
(
void
)
{
{
return
io
.
thread
!=
NULL
&&
g_thread_self
()
==
io
.
thread
;
return
io
.
thread
.
IsInside
()
;
}
}
src/OutputAll.cxx
View file @
8e676db6
...
@@ -33,6 +33,8 @@
...
@@ -33,6 +33,8 @@
#include "ConfigOption.hxx"
#include "ConfigOption.hxx"
#include "notify.hxx"
#include "notify.hxx"
#include <glib.h>
#include <assert.h>
#include <assert.h>
#include <string.h>
#include <string.h>
...
...
src/OutputControl.cxx
View file @
8e676db6
...
@@ -107,7 +107,7 @@ audio_output_set_replay_gain_mode(struct audio_output *ao,
...
@@ -107,7 +107,7 @@ audio_output_set_replay_gain_mode(struct audio_output *ao,
void
void
audio_output_enable
(
struct
audio_output
*
ao
)
audio_output_enable
(
struct
audio_output
*
ao
)
{
{
if
(
ao
->
thread
==
NULL
)
{
if
(
!
ao
->
thread
.
IsDefined
()
)
{
if
(
ao
->
plugin
->
enable
==
NULL
)
{
if
(
ao
->
plugin
->
enable
==
NULL
)
{
/* don't bother to start the thread now if the
/* don't bother to start the thread now if the
device doesn't even have a enable() method;
device doesn't even have a enable() method;
...
@@ -125,7 +125,7 @@ audio_output_enable(struct audio_output *ao)
...
@@ -125,7 +125,7 @@ audio_output_enable(struct audio_output *ao)
void
void
audio_output_disable
(
struct
audio_output
*
ao
)
audio_output_disable
(
struct
audio_output
*
ao
)
{
{
if
(
ao
->
thread
==
NULL
)
{
if
(
!
ao
->
thread
.
IsDefined
()
)
{
if
(
ao
->
plugin
->
disable
==
NULL
)
if
(
ao
->
plugin
->
disable
==
NULL
)
ao
->
really_enabled
=
false
;
ao
->
really_enabled
=
false
;
else
else
...
@@ -184,7 +184,7 @@ audio_output_open(struct audio_output *ao,
...
@@ -184,7 +184,7 @@ audio_output_open(struct audio_output *ao,
ao
->
pipe
=
&
mp
;
ao
->
pipe
=
&
mp
;
if
(
ao
->
thread
==
NULL
)
if
(
!
ao
->
thread
.
IsDefined
()
)
audio_output_thread_start
(
ao
);
audio_output_thread_start
(
ao
);
ao_command
(
ao
,
ao
->
open
?
AO_COMMAND_REOPEN
:
AO_COMMAND_OPEN
);
ao_command
(
ao
,
ao
->
open
?
AO_COMMAND_REOPEN
:
AO_COMMAND_OPEN
);
...
@@ -322,11 +322,10 @@ void audio_output_finish(struct audio_output *ao)
...
@@ -322,11 +322,10 @@ void audio_output_finish(struct audio_output *ao)
assert
(
ao
->
fail_timer
==
NULL
);
assert
(
ao
->
fail_timer
==
NULL
);
if
(
ao
->
thread
!=
NULL
)
{
if
(
ao
->
thread
.
IsDefined
()
)
{
assert
(
ao
->
allow_play
);
assert
(
ao
->
allow_play
);
ao_lock_command
(
ao
,
AO_COMMAND_KILL
);
ao_lock_command
(
ao
,
AO_COMMAND_KILL
);
g_thread_join
(
ao
->
thread
);
ao
->
thread
.
Join
();
ao
->
thread
=
NULL
;
}
}
audio_output_free
(
ao
);
audio_output_free
(
ao
);
...
...
src/OutputFinish.cxx
View file @
8e676db6
...
@@ -30,7 +30,7 @@ ao_base_finish(struct audio_output *ao)
...
@@ -30,7 +30,7 @@ ao_base_finish(struct audio_output *ao)
{
{
assert
(
!
ao
->
open
);
assert
(
!
ao
->
open
);
assert
(
ao
->
fail_timer
==
NULL
);
assert
(
ao
->
fail_timer
==
NULL
);
assert
(
ao
->
thread
==
NULL
);
assert
(
!
ao
->
thread
.
IsDefined
()
);
if
(
ao
->
mixer
!=
NULL
)
if
(
ao
->
mixer
!=
NULL
)
mixer_free
(
ao
->
mixer
);
mixer_free
(
ao
->
mixer
);
...
@@ -45,7 +45,7 @@ audio_output_free(struct audio_output *ao)
...
@@ -45,7 +45,7 @@ audio_output_free(struct audio_output *ao)
{
{
assert
(
!
ao
->
open
);
assert
(
!
ao
->
open
);
assert
(
ao
->
fail_timer
==
NULL
);
assert
(
ao
->
fail_timer
==
NULL
);
assert
(
ao
->
thread
==
NULL
);
assert
(
!
ao
->
thread
.
IsDefined
()
);
ao_plugin_finish
(
ao
);
ao_plugin_finish
(
ao
);
}
}
src/OutputInit.cxx
View file @
8e676db6
...
@@ -202,7 +202,6 @@ ao_base_init(struct audio_output *ao,
...
@@ -202,7 +202,6 @@ ao_base_init(struct audio_output *ao,
"Failed to initialize filter chain for '%s'"
,
"Failed to initialize filter chain for '%s'"
,
ao
->
name
);
ao
->
name
);
ao
->
thread
=
NULL
;
ao
->
command
=
AO_COMMAND_NONE
;
ao
->
command
=
AO_COMMAND_NONE
;
ao
->
mixer
=
NULL
;
ao
->
mixer
=
NULL
;
...
...
src/OutputInternal.hxx
View file @
8e676db6
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include "pcm/PcmBuffer.hxx"
#include "pcm/PcmBuffer.hxx"
#include "thread/Mutex.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "thread/Cond.hxx"
#include "thread/Thread.hxx"
#include <time.h>
#include <time.h>
...
@@ -31,7 +32,6 @@ class Error;
...
@@ -31,7 +32,6 @@ class Error;
class
Filter
;
class
Filter
;
class
MusicPipe
;
class
MusicPipe
;
struct
config_param
;
struct
config_param
;
typedef
struct
_GThread
GThread
;
typedef
struct
_GTimer
GTimer
;
typedef
struct
_GTimer
GTimer
;
enum
audio_output_command
{
enum
audio_output_command
{
...
@@ -200,7 +200,7 @@ struct audio_output {
...
@@ -200,7 +200,7 @@ struct audio_output {
* The thread handle, or NULL if the output thread isn't
* The thread handle, or NULL if the output thread isn't
* running.
* running.
*/
*/
GThread
*
thread
;
Thread
thread
;
/**
/**
* The next command to be performed by the output thread.
* The next command to be performed by the output thread.
...
...
src/OutputThread.cxx
View file @
8e676db6
...
@@ -562,7 +562,8 @@ static void ao_pause(struct audio_output *ao)
...
@@ -562,7 +562,8 @@ static void ao_pause(struct audio_output *ao)
ao
->
pause
=
false
;
ao
->
pause
=
false
;
}
}
static
gpointer
audio_output_task
(
gpointer
arg
)
static
void
audio_output_task
(
void
*
arg
)
{
{
struct
audio_output
*
ao
=
(
struct
audio_output
*
)
arg
;
struct
audio_output
*
ao
=
(
struct
audio_output
*
)
arg
;
...
@@ -647,7 +648,7 @@ static gpointer audio_output_task(gpointer arg)
...
@@ -647,7 +648,7 @@ static gpointer audio_output_task(gpointer arg)
ao
->
chunk
=
NULL
;
ao
->
chunk
=
NULL
;
ao_command_finished
(
ao
);
ao_command_finished
(
ao
);
ao
->
mutex
.
unlock
();
ao
->
mutex
.
unlock
();
return
NULL
;
return
;
}
}
if
(
ao
->
open
&&
ao
->
allow_play
&&
ao_play
(
ao
))
if
(
ao
->
open
&&
ao
->
allow_play
&&
ao_play
(
ao
))
...
@@ -664,11 +665,7 @@ void audio_output_thread_start(struct audio_output *ao)
...
@@ -664,11 +665,7 @@ void audio_output_thread_start(struct audio_output *ao)
{
{
assert
(
ao
->
command
==
AO_COMMAND_NONE
);
assert
(
ao
->
command
==
AO_COMMAND_NONE
);
#if GLIB_CHECK_VERSION(2,32,0)
Error
error
;
ao
->
thread
=
g_thread_new
(
"output"
,
audio_output_task
,
ao
);
if
(
!
ao
->
thread
.
Start
(
audio_output_task
,
ao
,
error
))
#else
FatalError
(
error
);
GError
*
e
=
nullptr
;
if
(
!
(
ao
->
thread
=
g_thread_create
(
audio_output_task
,
ao
,
true
,
&
e
)))
FatalError
(
"Failed to spawn output task"
,
e
);
#endif
}
}
src/PlayerCommands.cxx
View file @
8e676db6
...
@@ -32,6 +32,8 @@
...
@@ -32,6 +32,8 @@
#include "AudioFormat.hxx"
#include "AudioFormat.hxx"
#include "ReplayGainConfig.hxx"
#include "ReplayGainConfig.hxx"
#include <glib.h>
#define COMMAND_STATUS_STATE "state"
#define COMMAND_STATUS_STATE "state"
#define COMMAND_STATUS_REPEAT "repeat"
#define COMMAND_STATUS_REPEAT "repeat"
#define COMMAND_STATUS_SINGLE "single"
#define COMMAND_STATUS_SINGLE "single"
...
...
src/PlayerControl.cxx
View file @
8e676db6
...
@@ -23,6 +23,8 @@
...
@@ -23,6 +23,8 @@
#include "Song.hxx"
#include "Song.hxx"
#include "DecoderControl.hxx"
#include "DecoderControl.hxx"
#include <glib.h>
#include <cmath>
#include <cmath>
#include <assert.h>
#include <assert.h>
...
@@ -31,7 +33,6 @@ player_control::player_control(unsigned _buffer_chunks,
...
@@ -31,7 +33,6 @@ player_control::player_control(unsigned _buffer_chunks,
unsigned
_buffered_before_play
)
unsigned
_buffered_before_play
)
:
buffer_chunks
(
_buffer_chunks
),
:
buffer_chunks
(
_buffer_chunks
),
buffered_before_play
(
_buffered_before_play
),
buffered_before_play
(
_buffered_before_play
),
thread
(
nullptr
),
command
(
PlayerCommand
::
NONE
),
command
(
PlayerCommand
::
NONE
),
state
(
PlayerState
::
STOP
),
state
(
PlayerState
::
STOP
),
error_type
(
PlayerError
::
NONE
),
error_type
(
PlayerError
::
NONE
),
...
@@ -100,11 +101,10 @@ player_control::UpdateAudio()
...
@@ -100,11 +101,10 @@ player_control::UpdateAudio()
void
void
player_control
::
Kill
()
player_control
::
Kill
()
{
{
assert
(
thread
!=
NULL
);
assert
(
thread
.
IsDefined
()
);
LockSynchronousCommand
(
PlayerCommand
::
EXIT
);
LockSynchronousCommand
(
PlayerCommand
::
EXIT
);
g_thread_join
(
thread
);
thread
.
Join
();
thread
=
NULL
;
idle_add
(
IDLE_PLAYER
);
idle_add
(
IDLE_PLAYER
);
}
}
...
...
src/PlayerControl.hxx
View file @
8e676db6
...
@@ -23,10 +23,9 @@
...
@@ -23,10 +23,9 @@
#include "AudioFormat.hxx"
#include "AudioFormat.hxx"
#include "thread/Mutex.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "thread/Cond.hxx"
#include "thread/Thread.hxx"
#include "util/Error.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <stdint.h>
#include <stdint.h>
struct
Song
;
struct
Song
;
...
@@ -95,9 +94,10 @@ struct player_control {
...
@@ -95,9 +94,10 @@ struct player_control {
unsigned
int
buffered_before_play
;
unsigned
int
buffered_before_play
;
/** the handle of the player thread, or NULL if the player
/**
thread isn't running */
* The handle of the player thread.
GThread
*
thread
;
*/
Thread
thread
;
/**
/**
* This lock protects #command, #state, #error.
* This lock protects #command, #state, #error.
...
@@ -199,7 +199,7 @@ struct player_control {
...
@@ -199,7 +199,7 @@ struct player_control {
* prior to calling this function.
* prior to calling this function.
*/
*/
void
Wait
()
{
void
Wait
()
{
assert
(
thread
==
g_thread_self
());
assert
(
thread
.
IsInside
());
cond
.
wait
(
mutex
);
cond
.
wait
(
mutex
);
}
}
...
@@ -210,7 +210,7 @@ struct player_control {
...
@@ -210,7 +210,7 @@ struct player_control {
* Caller must lock the object.
* Caller must lock the object.
*/
*/
void
ClientSignal
()
{
void
ClientSignal
()
{
assert
(
thread
==
g_thread_self
());
assert
(
thread
.
IsInside
());
client_cond
.
signal
();
client_cond
.
signal
();
}
}
...
@@ -222,7 +222,7 @@ struct player_control {
...
@@ -222,7 +222,7 @@ struct player_control {
* Caller must lock the object.
* Caller must lock the object.
*/
*/
void
ClientWait
()
{
void
ClientWait
()
{
assert
(
thread
!=
g_thread_self
());
assert
(
!
thread
.
IsInside
());
client_cond
.
wait
(
mutex
);
client_cond
.
wait
(
mutex
);
}
}
...
...
src/PlayerThread.cxx
View file @
8e676db6
...
@@ -1096,8 +1096,8 @@ do_play(player_control &pc, decoder_control &dc,
...
@@ -1096,8 +1096,8 @@ do_play(player_control &pc, decoder_control &dc,
player
.
Run
();
player
.
Run
();
}
}
static
gpointer
static
void
player_task
(
gpointer
arg
)
player_task
(
void
*
arg
)
{
{
player_control
&
pc
=
*
(
player_control
*
)
arg
;
player_control
&
pc
=
*
(
player_control
*
)
arg
;
...
@@ -1163,7 +1163,7 @@ player_task(gpointer arg)
...
@@ -1163,7 +1163,7 @@ player_task(gpointer arg)
audio_output_all_close
();
audio_output_all_close
();
player_command_finished
(
pc
);
player_command_finished
(
pc
);
return
nullptr
;
return
;
case
PlayerCommand
:
:
CANCEL
:
case
PlayerCommand
:
:
CANCEL
:
if
(
pc
.
next_song
!=
nullptr
)
{
if
(
pc
.
next_song
!=
nullptr
)
{
...
@@ -1189,14 +1189,9 @@ player_task(gpointer arg)
...
@@ -1189,14 +1189,9 @@ player_task(gpointer arg)
void
void
player_create
(
player_control
&
pc
)
player_create
(
player_control
&
pc
)
{
{
assert
(
pc
.
thread
==
nullptr
);
assert
(
!
pc
.
thread
.
IsDefined
());
#if GLIB_CHECK_VERSION(2,32,0)
Error
error
;
pc
.
thread
=
g_thread_new
(
"player"
,
player_task
,
&
pc
);
if
(
!
pc
.
thread
.
Start
(
player_task
,
&
pc
,
error
))
#else
FatalError
(
error
);
GError
*
e
=
nullptr
;
pc
.
thread
=
g_thread_create
(
player_task
,
&
pc
,
true
,
&
e
);
if
(
pc
.
thread
==
nullptr
)
FatalError
(
"Failed to spawn player task"
,
e
);
#endif
}
}
src/PlaylistState.cxx
View file @
8e676db6
...
@@ -33,6 +33,8 @@
...
@@ -33,6 +33,8 @@
#include "ConfigOption.hxx"
#include "ConfigOption.hxx"
#include "Log.hxx"
#include "Log.hxx"
#include <glib.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
...
...
src/QueueCommands.cxx
View file @
8e676db6
...
@@ -35,6 +35,8 @@
...
@@ -35,6 +35,8 @@
#include "util/Error.hxx"
#include "util/Error.hxx"
#include "fs/Path.hxx"
#include "fs/Path.hxx"
#include <glib.h>
#include <string.h>
#include <string.h>
enum
command_return
enum
command_return
...
...
src/UpdateGlue.cxx
View file @
8e676db6
...
@@ -34,6 +34,7 @@
...
@@ -34,6 +34,7 @@
#include "Instance.hxx"
#include "Instance.hxx"
#include "system/FatalError.hxx"
#include "system/FatalError.hxx"
#include "thread/Id.hxx"
#include "thread/Id.hxx"
#include "thread/Thread.hxx"
#include <glib.h>
#include <glib.h>
...
@@ -47,7 +48,7 @@ static enum update_progress {
...
@@ -47,7 +48,7 @@ static enum update_progress {
static
bool
modified
;
static
bool
modified
;
static
GThread
*
update_thr
;
static
Thread
update_thread
;
static
const
unsigned
update_task_id_max
=
1
<<
15
;
static
const
unsigned
update_task_id_max
=
1
<<
15
;
...
@@ -62,7 +63,8 @@ isUpdatingDB(void)
...
@@ -62,7 +63,8 @@ isUpdatingDB(void)
return
(
progress
!=
UPDATE_PROGRESS_IDLE
)
?
update_task_id
:
0
;
return
(
progress
!=
UPDATE_PROGRESS_IDLE
)
?
update_task_id
:
0
;
}
}
static
void
*
update_task
(
void
*
_path
)
static
void
update_task
(
void
*
_path
)
{
{
const
char
*
path
=
(
const
char
*
)
_path
;
const
char
*
path
=
(
const
char
*
)
_path
;
...
@@ -87,7 +89,6 @@ static void * update_task(void *_path)
...
@@ -87,7 +89,6 @@ static void * update_task(void *_path)
progress
=
UPDATE_PROGRESS_DONE
;
progress
=
UPDATE_PROGRESS_DONE
;
GlobalEvents
::
Emit
(
GlobalEvents
::
UPDATE
);
GlobalEvents
::
Emit
(
GlobalEvents
::
UPDATE
);
return
NULL
;
}
}
static
void
static
void
...
@@ -98,14 +99,9 @@ spawn_update_task(const char *path)
...
@@ -98,14 +99,9 @@ spawn_update_task(const char *path)
progress
=
UPDATE_PROGRESS_RUNNING
;
progress
=
UPDATE_PROGRESS_RUNNING
;
modified
=
false
;
modified
=
false
;
#if GLIB_CHECK_VERSION(2,32,0)
Error
error
;
update_thr
=
g_thread_new
(
"update"
,
update_task
,
g_strdup
(
path
));
if
(
!
update_thread
.
Start
(
update_task
,
g_strdup
(
path
),
error
))
#else
FatalError
(
error
);
GError
*
e
=
NULL
;
update_thr
=
g_thread_create
(
update_task
,
g_strdup
(
path
),
TRUE
,
&
e
);
if
(
update_thr
==
NULL
)
FatalError
(
"Failed to spawn update task"
,
e
);
#endif
if
(
++
update_task_id
>
update_task_id_max
)
if
(
++
update_task_id
>
update_task_id_max
)
update_task_id
=
1
;
update_task_id
=
1
;
...
@@ -147,7 +143,7 @@ static void update_finished_event(void)
...
@@ -147,7 +143,7 @@ static void update_finished_event(void)
assert
(
progress
==
UPDATE_PROGRESS_DONE
);
assert
(
progress
==
UPDATE_PROGRESS_DONE
);
g_thread_join
(
update_thr
);
update_thread
.
Join
(
);
idle_add
(
IDLE_UPDATE
);
idle_add
(
IDLE_UPDATE
);
...
...
src/thread/Thread.cxx
0 → 100644
View file @
8e676db6
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "Thread.hxx"
#include "util/Error.hxx"
bool
Thread
::
Start
(
void
(
*
_f
)(
void
*
ctx
),
void
*
_ctx
,
Error
&
error
)
{
assert
(
!
IsDefined
());
f
=
_f
;
ctx
=
_ctx
;
#ifdef WIN32
handle
=
::
CreateThread
(
nullptr
,
0
,
ThreadProc
,
this
,
0
,
&
id
);
if
(
handle
==
nullptr
)
{
error
.
SetLastError
(
"Failed to create thread"
);
return
false
;
}
#else
#ifndef NDEBUG
creating
=
true
;
#endif
int
e
=
pthread_create
(
&
handle
,
nullptr
,
ThreadProc
,
this
);
if
(
e
!=
0
)
{
#ifndef NDEBUG
creating
=
false
;
#endif
error
.
SetErrno
(
e
,
"Failed to create thread"
);
return
false
;
}
defined
=
true
;
#ifndef NDEBUG
creating
=
false
;
#endif
#endif
return
true
;
}
void
Thread
::
Join
()
{
assert
(
IsDefined
());
assert
(
!
IsInside
());
#ifdef WIN32
::
WaitForSingleObject
(
handle
,
INFINITE
);
::
CloseHandle
(
handle
);
handle
=
nullptr
;
#else
pthread_join
(
handle
,
nullptr
);
defined
=
false
;
#endif
}
#ifdef WIN32
DWORD
WINAPI
Thread
::
ThreadProc
(
LPVOID
ctx
)
{
Thread
&
thread
=
*
(
Thread
*
)
ctx
;
thread
.
f
(
thread
.
ctx
);
return
0
;
}
#else
void
*
Thread
::
ThreadProc
(
void
*
ctx
)
{
Thread
&
thread
=
*
(
Thread
*
)
ctx
;
#ifndef NDEBUG
/* this works around a race condition that causes an assertion
failure due to IsInside() spuriously returning false right
after the thread has been created, and the calling thread
hasn't initialised "defined" yet */
thread
.
defined
=
true
;
#endif
thread
.
f
(
thread
.
ctx
);
return
nullptr
;
}
#endif
src/thread/Thread.hxx
0 → 100644
View file @
8e676db6
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_THREAD_HXX
#define MPD_THREAD_HXX
#include "check.h"
#include "Compiler.h"
#ifdef WIN32
#include <windows.h>
#else
#include <pthread.h>
#endif
#include <assert.h>
class
Error
;
class
Thread
{
#ifdef WIN32
HANDLE
handle
;
DWORD
id
;
#else
pthread_t
handle
;
bool
defined
;
#ifndef NDEBUG
/**
* The thread is currently being created. This is a workaround for
* IsInside(), which may return false until pthread_create() has
* initialised the #handle.
*/
bool
creating
;
#endif
#endif
void
(
*
f
)(
void
*
ctx
);
void
*
ctx
;
public
:
#ifdef WIN32
Thread
()
:
handle
(
nullptr
)
{}
#else
Thread
()
:
defined
(
false
)
{
#ifndef NDEBUG
creating
=
false
;
#endif
}
#endif
Thread
(
const
Thread
&
)
=
delete
;
#ifndef NDEBUG
virtual
~
Thread
()
{
/* all Thread objects must be destructed manually by calling
Join(), to clean up */
assert
(
!
IsDefined
());
}
#endif
bool
IsDefined
()
const
{
#ifdef WIN32
return
handle
!=
nullptr
;
#else
return
defined
;
#endif
}
/**
* Check if this thread is the current thread.
*/
gcc_pure
bool
IsInside
()
const
{
#ifdef WIN32
return
GetCurrentThreadId
()
==
id
;
#else
#ifdef NDEBUG
constexpr
bool
creating
=
false
;
#endif
return
IsDefined
()
&&
(
creating
||
pthread_equal
(
pthread_self
(),
handle
));
#endif
}
bool
Start
(
void
(
*
f
)(
void
*
ctx
),
void
*
ctx
,
Error
&
error
);
void
Join
();
private
:
#ifdef WIN32
static
DWORD
WINAPI
ThreadProc
(
LPVOID
ctx
);
#else
static
void
*
ThreadProc
(
void
*
ctx
);
#endif
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment