diff options
author | Max Kellermann <max@duempel.org> | 2013-11-06 23:10:05 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-11-06 23:51:17 +0100 |
commit | 0be5a6ab2b9201e60f3ecb363fcc9342ecfa8aee (patch) | |
tree | 0e1a98376069ab299dbd701d7be40f8030da70f8 | |
parent | 9802e74859219ae151cddb238f71016e3a2ef1ef (diff) |
DecoderControl: reduce the number of PlayerThread wakeups
Wake up the PlayerThread only if it is really waiting for the decoder.
This greatly reduces the number of system calls in the DecoderThread.
-rw-r--r-- | src/DecoderControl.cxx | 13 | ||||
-rw-r--r-- | src/DecoderControl.hxx | 14 | ||||
-rw-r--r-- | src/DecoderInternal.cxx | 3 |
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(); } |