lib/alsa/NonBlock: add common base class

This commit is contained in:
Max Kellermann 2024-07-11 21:26:47 +02:00
parent 3db8a4f41b
commit 4486b2eded
2 changed files with 45 additions and 32 deletions

View File

@ -7,6 +7,25 @@
namespace Alsa {
std::span<pollfd>
NonBlock::CopyReturnedEvents(MultiSocketMonitor &m, std::size_t n) noexcept
{
const auto pfds = buffer.Get(n), end = pfds + n;
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;
});
return {pfds, static_cast<std::size_t>(i - pfds)};
}
Event::Duration
NonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
{
@ -18,9 +37,9 @@ NonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
throw Alsa::MakeError(count, "snd_pcm_poll_descriptors_count() failed");
}
struct pollfd *pfds = pfd_buffer.Get(count);
const auto pfds = base.Allocate(count);
count = snd_pcm_poll_descriptors(pcm, pfds, count);
count = snd_pcm_poll_descriptors(pcm, pfds.data(), count);
if (count <= 0) {
if (count == 0)
throw std::runtime_error("snd_pcm_poll_descriptors() failed");
@ -28,7 +47,7 @@ NonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
throw Alsa::MakeError(count, "snd_pcm_poll_descriptors() failed");
}
m.ReplaceSocketList({pfds, static_cast<std::size_t>(count)});
m.ReplaceSocketList(pfds.first(count));
return Event::Duration(-1);
}
@ -39,20 +58,10 @@ NonBlockPcm::DispatchSockets(MultiSocketMonitor &m, snd_pcm_t *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;
});
const auto pfds = base.CopyReturnedEvents(m, count);
unsigned short dummy;
int err = snd_pcm_poll_descriptors_revents(pcm, pfds, i - pfds, &dummy);
int err = snd_pcm_poll_descriptors_revents(pcm, pfds.data(), pfds.size(), &dummy);
if (err < 0)
throw Alsa::MakeError(err, "snd_pcm_poll_descriptors_revents() failed");
}
@ -66,13 +75,13 @@ NonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcep
return Event::Duration(-1);
}
struct pollfd *pfds = pfd_buffer.Get(count);
const auto pfds = base.Allocate(count);
count = snd_mixer_poll_descriptors(mixer, pfds, count);
count = snd_mixer_poll_descriptors(mixer, pfds.data(), count);
if (count < 0)
count = 0;
m.ReplaceSocketList({pfds, static_cast<std::size_t>(count)});
m.ReplaceSocketList(pfds.first(count));
return Event::Duration(-1);
}
@ -83,20 +92,10 @@ NonBlockMixer::DispatchSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexce
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;
});
const auto pfds = base.CopyReturnedEvents(m, count);
unsigned short dummy;
snd_mixer_poll_descriptors_revents(mixer, pfds, i - pfds, &dummy);
snd_mixer_poll_descriptors_revents(mixer, pfds.data(), pfds.size(), &dummy);
}
} // namespace Alsa

View File

@ -8,16 +8,30 @@
#include <alsa/asoundlib.h>
#include <span>
class MultiSocketMonitor;
namespace Alsa {
class NonBlock {
ReusableArray<pollfd> buffer;
public:
std::span<pollfd> Allocate(std::size_t n) noexcept {
return {buffer.Get(n), n};
}
std::span<pollfd> CopyReturnedEvents(MultiSocketMonitor &m,
std::size_t n) noexcept;
};
/**
* Helper class for #MultiSocketMonitor's virtual methods which
* manages the file descriptors for a #snd_pcm_t.
*/
class NonBlockPcm {
ReusableArray<pollfd> pfd_buffer;
NonBlock base;
public:
/**
@ -40,7 +54,7 @@ public:
* manages the file descriptors for a #snd_mixer_t.
*/
class NonBlockMixer {
ReusableArray<pollfd> pfd_buffer;
NonBlock base;
public:
Event::Duration PrepareSockets(MultiSocketMonitor &m,