mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:57:47 +00:00
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:
parent
4a8683ea68
commit
a089125d0f
2 changed files with 19 additions and 15 deletions
|
@ -2,19 +2,25 @@
|
||||||
#include <AudioServer/ASClientConnection.h>
|
#include <AudioServer/ASClientConnection.h>
|
||||||
#include <AudioServer/ASMixer.h>
|
#include <AudioServer/ASMixer.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
ASMixer::ASMixer()
|
ASMixer::ASMixer()
|
||||||
: m_device(CFile::construct("/dev/audio", this))
|
: m_device(CFile::construct("/dev/audio", this))
|
||||||
, m_sound_thread([this] {
|
, m_sound_thread(
|
||||||
mix();
|
[this] {
|
||||||
return 0;
|
mix();
|
||||||
}, "AudioServer[mixer]")
|
return 0;
|
||||||
|
},
|
||||||
|
"AudioServer[mixer]")
|
||||||
{
|
{
|
||||||
if (!m_device->open(CIODevice::WriteOnly)) {
|
if (!m_device->open(CIODevice::WriteOnly)) {
|
||||||
dbgprintf("Can't open audio device: %s\n", m_device->error_string());
|
dbgprintf("Can't open audio device: %s\n", m_device->error_string());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_init(&m_pending_mutex, nullptr);
|
||||||
|
pthread_cond_init(&m_pending_cond, nullptr);
|
||||||
|
|
||||||
m_zero_filled_buffer = (u8*)malloc(4096);
|
m_zero_filled_buffer = (u8*)malloc(4096);
|
||||||
bzero(m_zero_filled_buffer, 4096);
|
bzero(m_zero_filled_buffer, 4096);
|
||||||
m_sound_thread.start();
|
m_sound_thread.start();
|
||||||
|
@ -26,9 +32,11 @@ ASMixer::~ASMixer()
|
||||||
|
|
||||||
NonnullRefPtr<ASBufferQueue> ASMixer::create_queue(ASClientConnection& client)
|
NonnullRefPtr<ASBufferQueue> ASMixer::create_queue(ASClientConnection& client)
|
||||||
{
|
{
|
||||||
LOCKER(m_lock);
|
|
||||||
auto queue = adopt(*new ASBufferQueue(client));
|
auto queue = adopt(*new ASBufferQueue(client));
|
||||||
|
pthread_mutex_lock(&m_pending_mutex);
|
||||||
m_pending_mixing.append(*queue);
|
m_pending_mixing.append(*queue);
|
||||||
|
pthread_cond_signal(&m_pending_cond);
|
||||||
|
pthread_mutex_unlock(&m_pending_mutex);
|
||||||
return queue;
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,16 +45,11 @@ void ASMixer::mix()
|
||||||
decltype(m_pending_mixing) active_mix_queues;
|
decltype(m_pending_mixing) active_mix_queues;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
{
|
if (active_mix_queues.is_empty()) {
|
||||||
LOCKER(m_lock);
|
pthread_mutex_lock(&m_pending_mutex);
|
||||||
|
pthread_cond_wait(&m_pending_cond, &m_pending_mutex);
|
||||||
active_mix_queues.append(move(m_pending_mixing));
|
active_mix_queues.append(move(m_pending_mixing));
|
||||||
}
|
pthread_mutex_unlock(&m_pending_mutex);
|
||||||
|
|
||||||
// ### use a wakeup of some kind rather than this garbage
|
|
||||||
if (active_mix_queues.size() == 0) {
|
|
||||||
// nothing to mix yet
|
|
||||||
usleep(10000);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
active_mix_queues.remove_all_matching([&](auto& entry) { return !entry->client(); });
|
active_mix_queues.remove_all_matching([&](auto& entry) { return !entry->client(); });
|
||||||
|
|
|
@ -96,9 +96,10 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<NonnullRefPtr<ASBufferQueue>> m_pending_mixing;
|
Vector<NonnullRefPtr<ASBufferQueue>> m_pending_mixing;
|
||||||
|
pthread_mutex_t m_pending_mutex;
|
||||||
|
pthread_cond_t m_pending_cond;
|
||||||
|
|
||||||
RefPtr<CFile> m_device;
|
RefPtr<CFile> m_device;
|
||||||
LibThread::Lock m_lock;
|
|
||||||
|
|
||||||
LibThread::Thread m_sound_thread;
|
LibThread::Thread m_sound_thread;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue