diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx
index ceb8d64b6..801a16fd0 100644
--- a/src/input/plugins/AlsaInputPlugin.cxx
+++ b/src/input/plugins/AlsaInputPlugin.cxx
@@ -34,7 +34,6 @@
 #include "util/Domain.hxx"
 #include "util/RuntimeError.hxx"
 #include "util/StringCompare.hxx"
-#include "util/ReusableArray.hxx"
 #include "util/ASCII.hxx"
 #include "Log.hxx"
 #include "event/MultiSocketMonitor.hxx"
@@ -69,7 +68,7 @@ class AlsaInputStream final
 	snd_pcm_t *const capture_handle;
 	const size_t frame_size;
 
-	ReusableArray<pollfd> pfd_buffer;
+	AlsaNonBlockPcm non_block;
 
 	DeferEvent defer_invalidate_sockets;
 
@@ -180,7 +179,7 @@ AlsaInputStream::PrepareSockets() noexcept
 		return std::chrono::steady_clock::duration(-1);
 	}
 
-	return PrepareAlsaPcmSockets(*this, capture_handle, pfd_buffer);
+	return non_block.PrepareSockets(*this, capture_handle);
 }
 
 void
diff --git a/src/lib/alsa/NonBlock.cxx b/src/lib/alsa/NonBlock.cxx
index cbbc46268..589def151 100644
--- a/src/lib/alsa/NonBlock.cxx
+++ b/src/lib/alsa/NonBlock.cxx
@@ -23,8 +23,7 @@
 #include "util/RuntimeError.hxx"
 
 std::chrono::steady_clock::duration
-PrepareAlsaPcmSockets(MultiSocketMonitor &m, snd_pcm_t *pcm,
-		      ReusableArray<pollfd> &pfd_buffer)
+AlsaNonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
 {
 	int count = snd_pcm_poll_descriptors_count(pcm);
 	if (count <= 0) {
@@ -51,8 +50,7 @@ PrepareAlsaPcmSockets(MultiSocketMonitor &m, snd_pcm_t *pcm,
 }
 
 std::chrono::steady_clock::duration
-PrepareAlsaMixerSockets(MultiSocketMonitor &m, snd_mixer_t *mixer,
-			ReusableArray<pollfd> &pfd_buffer) noexcept
+AlsaNonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept
 {
 	int count = snd_mixer_poll_descriptors_count(mixer);
 	if (count <= 0) {
diff --git a/src/lib/alsa/NonBlock.hxx b/src/lib/alsa/NonBlock.hxx
index c8719c058..8d6e42458 100644
--- a/src/lib/alsa/NonBlock.hxx
+++ b/src/lib/alsa/NonBlock.hxx
@@ -30,23 +30,30 @@
 class MultiSocketMonitor;
 
 /**
- * Update #MultiSocketMonitor's socket list from
- * snd_pcm_poll_descriptors().  To be called from
- * MultiSocketMonitor::PrepareSockets().
- *
- * Throws exception on error.
+ * Helper class for #MultiSocketMonitor's virtual methods which
+ * manages the file descriptors for a #snd_pcm_t.
  */
-std::chrono::steady_clock::duration
-PrepareAlsaPcmSockets(MultiSocketMonitor &m, snd_pcm_t *pcm,
-		      ReusableArray<pollfd> &pfd_buffer);
+class AlsaNonBlockPcm {
+	ReusableArray<pollfd> pfd_buffer;
+
+public:
+	/**
+	 * Throws on error.
+	 */
+	std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m,
+							   snd_pcm_t *pcm);
+};
 
 /**
- * Update #MultiSocketMonitor's socket list from
- * snd_mixer_poll_descriptors().  To be called from
- * MultiSocketMonitor::PrepareSockets().
+ * Helper class for #MultiSocketMonitor's virtual methods which
+ * manages the file descriptors for a #snd_mixer_t.
  */
-std::chrono::steady_clock::duration
-PrepareAlsaMixerSockets(MultiSocketMonitor &m, snd_mixer_t *mixer,
-		      ReusableArray<pollfd> &pfd_buffer) noexcept;
+class AlsaNonBlockMixer {
+	ReusableArray<pollfd> pfd_buffer;
+
+public:
+	std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m,
+							   snd_mixer_t *mixer) noexcept;
+};
 
 #endif
diff --git a/src/mixer/plugins/AlsaMixerPlugin.cxx b/src/mixer/plugins/AlsaMixerPlugin.cxx
index 7dd8ab853..dbc74d941 100644
--- a/src/mixer/plugins/AlsaMixerPlugin.cxx
+++ b/src/mixer/plugins/AlsaMixerPlugin.cxx
@@ -26,7 +26,6 @@
 #include "event/DeferEvent.hxx"
 #include "event/Call.hxx"
 #include "util/ASCII.hxx"
-#include "util/ReusableArray.hxx"
 #include "util/Domain.hxx"
 #include "util/RuntimeError.hxx"
 #include "Log.hxx"
@@ -48,7 +47,7 @@ class AlsaMixerMonitor final : MultiSocketMonitor {
 
 	snd_mixer_t *mixer;
 
-	ReusableArray<pollfd> pfd_buffer;
+	AlsaNonBlockMixer non_block;
 
 public:
 	AlsaMixerMonitor(EventLoop &_loop, snd_mixer_t *_mixer)
@@ -110,7 +109,7 @@ AlsaMixerMonitor::PrepareSockets() noexcept
 		return std::chrono::steady_clock::duration(-1);
 	}
 
-	return PrepareAlsaMixerSockets(*this, mixer, pfd_buffer);
+	return non_block.PrepareSockets(*this, mixer);
 }
 
 void
diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx
index 5c6f599cd..02b3dfe86 100644
--- a/src/output/plugins/AlsaOutputPlugin.cxx
+++ b/src/output/plugins/AlsaOutputPlugin.cxx
@@ -148,10 +148,7 @@ class AlsaOutput final
 	 */
 	uint8_t *silence;
 
-	/**
-	 * For PrepareAlsaPcmSockets().
-	 */
-	ReusableArray<pollfd> pfd_buffer;
+	AlsaNonBlockPcm non_block;
 
 	/**
 	 * For copying data from OutputThread to IOThread.
@@ -881,7 +878,7 @@ AlsaOutput::PrepareSockets() noexcept
 	}
 
 	try {
-		return PrepareAlsaPcmSockets(*this, pcm, pfd_buffer);
+		return non_block.PrepareSockets(*this, pcm);
 	} catch (...) {
 		ClearSocketList();
 		LockCaughtError();