From 0be5a6ab2b9201e60f3ecb363fcc9342ecfa8aee Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 6 Nov 2013 23:10:05 +0100 Subject: 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. --- src/DecoderControl.cxx | 13 +++++++++++++ src/DecoderControl.hxx | 14 +++++++++++--- 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(); } -- cgit v1.2.3