AudioServer: Block the mixer thread when there's nothing to do

Use a pthread_cond_t to have the ASMixer thread wait until a client has
connected and added a buffer queue to the "pending mixing" vector.

This solves the long-standing issue of the system "idling" at ~8% CPU.
This commit is contained in:
Andreas Kling 2019-12-22 21:33:33 +01:00
parent 4a8683ea68
commit a089125d0f
2 changed files with 19 additions and 15 deletions

View file

@ -2,19 +2,25 @@
#include <AudioServer/ASClientConnection.h>
#include <AudioServer/ASMixer.h>
#include <limits>
#include <pthread.h>
ASMixer::ASMixer()
: m_device(CFile::construct("/dev/audio", this))
, m_sound_thread([this] {
mix();
return 0;
}, "AudioServer[mixer]")
, m_sound_thread(
[this] {
mix();
return 0;
},
"AudioServer[mixer]")
{
if (!m_device->open(CIODevice::WriteOnly)) {
dbgprintf("Can't open audio device: %s\n", m_device->error_string());
return;
}
pthread_mutex_init(&m_pending_mutex, nullptr);
pthread_cond_init(&m_pending_cond, nullptr);
m_zero_filled_buffer = (u8*)malloc(4096);
bzero(m_zero_filled_buffer, 4096);
m_sound_thread.start();
@ -26,9 +32,11 @@ ASMixer::~ASMixer()
NonnullRefPtr<ASBufferQueue> ASMixer::create_queue(ASClientConnection& client)
{
LOCKER(m_lock);
auto queue = adopt(*new ASBufferQueue(client));
pthread_mutex_lock(&m_pending_mutex);
m_pending_mixing.append(*queue);
pthread_cond_signal(&m_pending_cond);
pthread_mutex_unlock(&m_pending_mutex);
return queue;
}
@ -37,16 +45,11 @@ void ASMixer::mix()
decltype(m_pending_mixing) active_mix_queues;
for (;;) {
{
LOCKER(m_lock);
if (active_mix_queues.is_empty()) {
pthread_mutex_lock(&m_pending_mutex);
pthread_cond_wait(&m_pending_cond, &m_pending_mutex);
active_mix_queues.append(move(m_pending_mixing));
}
// ### use a wakeup of some kind rather than this garbage
if (active_mix_queues.size() == 0) {
// nothing to mix yet
usleep(10000);
continue;
pthread_mutex_unlock(&m_pending_mutex);
}
active_mix_queues.remove_all_matching([&](auto& entry) { return !entry->client(); });

View file

@ -96,9 +96,10 @@ public:
private:
Vector<NonnullRefPtr<ASBufferQueue>> m_pending_mixing;
pthread_mutex_t m_pending_mutex;
pthread_cond_t m_pending_cond;
RefPtr<CFile> m_device;
LibThread::Lock m_lock;
LibThread::Thread m_sound_thread;