player/Control: add "occupied" flag to skip REFRESH

Reduces main thread contention.  Avoids blocking the main thread in
"status" commands.
This commit is contained in:
Max Kellermann 2017-12-20 20:27:19 +01:00
parent 994c9a01e3
commit a431274b32
3 changed files with 30 additions and 1 deletions

View File

@ -44,6 +44,7 @@ PlayerControl::PlayerControl(PlayerListener &_listener,
PlayerControl::~PlayerControl() noexcept
{
assert(!occupied);
}
bool
@ -155,7 +156,8 @@ PlayerControl::LockGetStatus() noexcept
player_status status;
const std::lock_guard<Mutex> protect(mutex);
SynchronousCommand(PlayerCommand::REFRESH);
if (!occupied)
SynchronousCommand(PlayerCommand::REFRESH);
status.state = state;

View File

@ -185,6 +185,29 @@ struct PlayerControl final : AudioOutputClient {
*/
bool border_pause = false;
/**
* If this flag is set, then the player thread is currently
* occupied and will not be able to respond quickly to
* commands (e.g. waiting for the decoder thread to finish
* seeking). This is used to skip #PlayerCommand::REFRESH to
* avoid blocking the main thread.
*/
bool occupied = false;
struct ScopeOccupied {
PlayerControl &pc;
explicit ScopeOccupied(PlayerControl &_pc) noexcept:pc(_pc) {
assert(!pc.occupied);
pc.occupied = true;
}
~ScopeOccupied() noexcept {
assert(pc.occupied);
pc.occupied = false;
}
};
AudioFormat audio_format;
uint16_t bit_rate;

View File

@ -367,6 +367,8 @@ Player::StartDecoder(MusicPipe &_pipe) noexcept
void
Player::StopDecoder() noexcept
{
const PlayerControl::ScopeOccupied occupied(pc);
dc.Stop();
if (dc.pipe != nullptr) {
@ -624,6 +626,8 @@ Player::SeekDecoder() noexcept
}
try {
const PlayerControl::ScopeOccupied occupied(pc);
dc.Seek(where + start_time);
} catch (...) {
/* decoder failure */