From 0e0bc7976fa2431699f01cadbc2dc486ddf7bd38 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Sun, 23 Sep 2018 17:15:08 +0200
Subject: [PATCH] player/Control: add LockGetSyncInfo()

---
 src/player/Control.hxx | 15 +++++++++++----
 src/queue/Playlist.cxx | 17 +++++------------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/player/Control.hxx b/src/player/Control.hxx
index c3ff23def..1bf41bb77 100644
--- a/src/player/Control.hxx
+++ b/src/player/Control.hxx
@@ -434,6 +434,17 @@ public:
 		return state;
 	}
 
+	struct SyncInfo {
+		PlayerState state;
+		bool has_next_song;
+	};
+
+	gcc_pure
+	SyncInfo LockGetSyncInfo() const noexcept {
+		const std::lock_guard<Mutex> protect(mutex);
+		return {state, next_song != nullptr};
+	}
+
 private:
 	/**
 	 * Set the error.  Discards any previous error condition.
@@ -527,10 +538,6 @@ public:
 	 */
 	void LockEnqueueSong(std::unique_ptr<DetachedSong> song) noexcept;
 
-	bool HasNextSong() const noexcept {
-		return next_song != nullptr;
-	}
-
 	/**
 	 * Makes the player thread seek the specified song to a position.
 	 *
diff --git a/src/queue/Playlist.cxx b/src/queue/Playlist.cxx
index 358cbee1a..dabeac5f2 100644
--- a/src/queue/Playlist.cxx
+++ b/src/queue/Playlist.cxx
@@ -91,7 +91,7 @@ playlist::SongStarted()
 inline void
 playlist::QueuedSongStarted(PlayerControl &pc)
 {
-	assert(!pc.HasNextSong());
+	assert(!pc.LockGetSyncInfo().has_next_song);
 	assert(queued >= -1);
 	assert(current >= 0);
 
@@ -195,12 +195,9 @@ playlist::SyncWithPlayer(PlayerControl &pc)
 		   playing anymore; ignore the event */
 		return;
 
-	pc.Lock();
-	const PlayerState pc_state = pc.GetState();
-	bool pc_has_next_song = pc.HasNextSong();
-	pc.Unlock();
+	const auto i = pc.LockGetSyncInfo();
 
-	if (pc_state == PlayerState::STOP)
+	if (i.state == PlayerState::STOP)
 		/* the player thread has stopped: check if playback
 		   should be restarted with the next song.  That can
 		   happen if the playlist isn't filling the queue fast
@@ -209,16 +206,12 @@ playlist::SyncWithPlayer(PlayerControl &pc)
 	else {
 		/* check if the player thread has already started
 		   playing the queued song */
-		if (!pc_has_next_song && queued != -1)
+		if (!i.has_next_song && queued != -1)
 			QueuedSongStarted(pc);
 
-		pc.Lock();
-		pc_has_next_song = pc.HasNextSong();
-		pc.Unlock();
-
 		/* make sure the queued song is always set (if
 		   possible) */
-		if (!pc_has_next_song && queued < 0)
+		if (!pc.LockGetSyncInfo().has_next_song && queued < 0)
 			UpdateQueuedSong(pc, nullptr);
 	}
 }