summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/DecoderControl.cxx13
-rw-r--r--src/DecoderControl.hxx14
-rw-r--r--src/DecoderInternal.cxx3
3 files changed, 26 insertions, 4 deletions
diff --git a/src/DecoderControl.cxx b/src/DecoderControl.cxx
index d76580cbb..ab460ced0 100644
--- a/src/DecoderControl.cxx
+++ b/src/DecoderControl.cxx
@@ -30,6 +30,7 @@ DecoderControl::DecoderControl(Mutex &_mutex, Cond &_client_cond)
:mutex(_mutex), client_cond(_client_cond),
state(DecoderState::STOP),
command(DecoderCommand::NONE),
+ client_is_waiting(false),
song(nullptr),
replay_gain_db(0), replay_gain_prev_db(0) {}
@@ -41,6 +42,18 @@ DecoderControl::~DecoderControl()
song->Free();
}
+void
+DecoderControl::WaitForDecoder()
+{
+ assert(!client_is_waiting);
+ client_is_waiting = true;
+
+ client_cond.wait(mutex);
+
+ assert(client_is_waiting);
+ client_is_waiting = false;
+}
+
bool
DecoderControl::IsCurrentSong(const Song &_song) const
{
diff --git a/src/DecoderControl.hxx b/src/DecoderControl.hxx
index 23cb394ca..863398dca 100644
--- a/src/DecoderControl.hxx
+++ b/src/DecoderControl.hxx
@@ -97,6 +97,14 @@ struct DecoderControl {
Error error;
bool quit;
+
+ /**
+ * Is the client currently waiting for the DecoderThread? If
+ * false, the DecoderThread may omit invoking Cond::signal(),
+ * reducing the number of system calls.
+ */
+ bool client_is_waiting;
+
bool seek_error;
bool seekable;
double seek_where;
@@ -193,10 +201,10 @@ struct DecoderControl {
* Waits for a signal from the decoder thread. This object
* must be locked prior to calling this function. This method
* is only valid in the player thread.
+ *
+ * Caller must hold the lock.
*/
- void WaitForDecoder() {
- client_cond.wait(mutex);
- }
+ void WaitForDecoder();
bool IsIdle() const {
return state == DecoderState::STOP ||
diff --git a/src/DecoderInternal.cxx b/src/DecoderInternal.cxx
index 7cca5dbe3..e18fd2b6a 100644
--- a/src/DecoderInternal.cxx
+++ b/src/DecoderInternal.cxx
@@ -102,6 +102,7 @@ decoder_flush_chunk(Decoder &decoder)
decoder.chunk = nullptr;
dc.Lock();
- dc.client_cond.signal();
+ if (dc.client_is_waiting)
+ dc.client_cond.signal();
dc.Unlock();
}