diff options
author | Max Kellermann <max@musicpd.org> | 2018-11-08 14:29:04 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2018-11-11 12:37:29 +0100 |
commit | fee75dc766995d9946af03b40861f19412b5edd9 (patch) | |
tree | 242adc4b5e923f637cfc1df9ca3c38dd54094856 /src/lib/alsa | |
parent | ba5c856f154fcfbbb6643e32e020c1c3bc2e8feb (diff) |
{output,mixer}/alsa: use snd_pcm_poll_descriptors_revents()
This call was missing, causing very high CPU usage when the ALSA
output plugin was used with dmix.
Closes #391
Diffstat (limited to 'src/lib/alsa')
-rw-r--r-- | src/lib/alsa/NonBlock.cxx | 48 | ||||
-rw-r--r-- | src/lib/alsa/NonBlock.hxx | 12 |
2 files changed, 60 insertions, 0 deletions
diff --git a/src/lib/alsa/NonBlock.cxx b/src/lib/alsa/NonBlock.cxx index 589def151..5b6667302 100644 --- a/src/lib/alsa/NonBlock.cxx +++ b/src/lib/alsa/NonBlock.cxx @@ -49,6 +49,30 @@ AlsaNonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm) return std::chrono::steady_clock::duration(-1); } +void +AlsaNonBlockPcm::DispatchSockets(MultiSocketMonitor &m, + snd_pcm_t *pcm) noexcept +{ + int count = snd_pcm_poll_descriptors_count(pcm); + if (count <= 0) + return; + + const auto pfds = pfd_buffer.Get(count), end = pfds + count; + + auto *i = pfds; + m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){ + if (i >= end) + return; + + i->fd = s.Get(); + i->events = i->revents = events; + ++i; + }); + + unsigned short dummy; + snd_pcm_poll_descriptors_revents(pcm, pfds, i - pfds, &dummy); +} + std::chrono::steady_clock::duration AlsaNonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept { @@ -67,3 +91,27 @@ AlsaNonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noe m.ReplaceSocketList(pfds, count); return std::chrono::steady_clock::duration(-1); } + +void +AlsaNonBlockMixer::DispatchSockets(MultiSocketMonitor &m, + snd_mixer_t *mixer) noexcept +{ + int count = snd_mixer_poll_descriptors_count(mixer); + if (count <= 0) + return; + + const auto pfds = pfd_buffer.Get(count), end = pfds + count; + + auto *i = pfds; + m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){ + if (i >= end) + return; + + i->fd = s.Get(); + i->events = i->revents = events; + ++i; + }); + + unsigned short dummy; + snd_mixer_poll_descriptors_revents(mixer, pfds, i - pfds, &dummy); +} diff --git a/src/lib/alsa/NonBlock.hxx b/src/lib/alsa/NonBlock.hxx index 8d6e42458..8e9e2c7f2 100644 --- a/src/lib/alsa/NonBlock.hxx +++ b/src/lib/alsa/NonBlock.hxx @@ -42,6 +42,12 @@ public: */ std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm); + + /** + * Wrapper for snd_pcm_poll_descriptors_revents(), to be + * called from MultiSocketMonitor::DispatchSockets(). + */ + void DispatchSockets(MultiSocketMonitor &m, snd_pcm_t *pcm) noexcept; }; /** @@ -54,6 +60,12 @@ class AlsaNonBlockMixer { public: std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept; + + /** + * Wrapper for snd_mixer_poll_descriptors_revents(), to be + * called from MultiSocketMonitor::DispatchSockets(). + */ + void DispatchSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept; }; #endif |