diff --git a/Userland/Libraries/LibAudio/ConnectionToServer.cpp b/Userland/Libraries/LibAudio/ConnectionToServer.cpp index e42ba7a07a..7f063f8502 100644 --- a/Userland/Libraries/LibAudio/ConnectionToServer.cpp +++ b/Userland/Libraries/LibAudio/ConnectionToServer.cpp @@ -62,8 +62,7 @@ ErrorOr ConnectionToServer::async_enqueue(FixedArray&& samples) update_good_sleep_time(); m_user_queue->append(move(samples)); // Wake the background thread to make sure it starts enqueuing audio. - if (!m_audio_enqueuer_active.load()) - m_enqueuer_loop->post_event(*this, make(0), Core::EventLoop::ShouldWake::Yes); + m_enqueuer_loop->wake_once(*this, 0); async_start_playback(); return {}; @@ -87,8 +86,6 @@ void ConnectionToServer::custom_event(Core::CustomEvent&) { Array next_chunk; while (true) { - m_audio_enqueuer_active.store(true); - if (m_user_queue->is_empty()) { dbgln("Reached end of provided audio data, going to sleep"); break; @@ -107,7 +104,6 @@ void ConnectionToServer::custom_event(Core::CustomEvent&) if (result.is_error()) dbgln("Error while writing samples to shared buffer: {}", result.error()); } - m_audio_enqueuer_active.store(false); } ErrorOr ConnectionToServer::realtime_enqueue(Array samples) diff --git a/Userland/Libraries/LibAudio/ConnectionToServer.h b/Userland/Libraries/LibAudio/ConnectionToServer.h index 154d7bb5b5..e14deab6c3 100644 --- a/Userland/Libraries/LibAudio/ConnectionToServer.h +++ b/Userland/Libraries/LibAudio/ConnectionToServer.h @@ -83,7 +83,6 @@ private: NonnullRefPtr m_background_audio_enqueuer; Core::EventLoop* m_enqueuer_loop; Threading::Mutex m_enqueuer_loop_destruction; - Atomic m_audio_enqueuer_active { false }; // A good amount of time to sleep when the queue is full. // (Only used for non-realtime enqueues) diff --git a/Userland/Libraries/LibCore/EventLoop.cpp b/Userland/Libraries/LibCore/EventLoop.cpp index 53dee35b39..6c76c45f95 100644 --- a/Userland/Libraries/LibCore/EventLoop.cpp +++ b/Userland/Libraries/LibCore/EventLoop.cpp @@ -501,6 +501,23 @@ void EventLoop::post_event(Object& receiver, NonnullOwnPtr&& event, Shoul wake(); } +void EventLoop::wake_once(Object& receiver, int custom_event_type) +{ + Threading::MutexLocker lock(m_private->lock); + dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::wake_once: event type {}", custom_event_type); + auto identical_events = m_queued_events.find_if([&](auto& queued_event) { + if (queued_event.receiver.is_null()) + return false; + auto const& event = queued_event.event; + auto is_receiver_identical = queued_event.receiver.ptr() == &receiver; + auto event_id_matches = event->type() == Event::Type::Custom && static_cast(event.ptr())->custom_type() == custom_event_type; + return is_receiver_identical && event_id_matches; + }); + // Event is not in the queue yet, so we want to wake. + if (identical_events.is_end()) + post_event(receiver, make(custom_event_type), ShouldWake::Yes); +} + SignalHandlers::SignalHandlers(int signo, void (*handle_signal)(int)) : m_signo(signo) , m_original_handler(signal(signo, handle_signal)) diff --git a/Userland/Libraries/LibCore/EventLoop.h b/Userland/Libraries/LibCore/EventLoop.h index 0599944489..ecdc104c63 100644 --- a/Userland/Libraries/LibCore/EventLoop.h +++ b/Userland/Libraries/LibCore/EventLoop.h @@ -56,6 +56,7 @@ public: void spin_until(Function); void post_event(Object& receiver, NonnullOwnPtr&&, ShouldWake = ShouldWake::No); + void wake_once(Object& receiver, int custom_event_type); static EventLoop& current();