diff --git a/Userland/Libraries/LibCore/DeferredInvocationContext.h b/Userland/Libraries/LibCore/DeferredInvocationContext.h index 5af46ff3dba..31ee2176d61 100644 --- a/Userland/Libraries/LibCore/DeferredInvocationContext.h +++ b/Userland/Libraries/LibCore/DeferredInvocationContext.h @@ -13,8 +13,21 @@ namespace Core { class DeferredInvocationContext final : public Core::EventReceiver { C_OBJECT(DeferredInvocationContext) +public: + bool should_invoke() const { return m_condition(); } + private: - DeferredInvocationContext() = default; + DeferredInvocationContext() + : m_condition([] { return true; }) + { + } + + DeferredInvocationContext(Function condition) + : m_condition(move(condition)) + { + } + + Function m_condition; }; } diff --git a/Userland/Libraries/LibCore/EventLoop.cpp b/Userland/Libraries/LibCore/EventLoop.cpp index bbe7667179e..417487c7008 100644 --- a/Userland/Libraries/LibCore/EventLoop.cpp +++ b/Userland/Libraries/LibCore/EventLoop.cpp @@ -156,11 +156,22 @@ void EventLoop::deferred_invoke(Function invokee) post_event(context, make(context, move(invokee))); } +void EventLoop::deferred_invoke_if(Function invokee, Function condition) +{ + auto context = DeferredInvocationContext::construct(move(condition)); + post_event(context, make(context, move(invokee))); +} + void deferred_invoke(Function invokee) { EventLoop::current().deferred_invoke(move(invokee)); } +void deferred_invoke_if(Function invokee, Function condition) +{ + EventLoop::current().deferred_invoke_if(move(invokee), move(condition)); +} + bool EventLoop::was_exit_requested() const { return m_impl->was_exit_requested(); diff --git a/Userland/Libraries/LibCore/EventLoop.h b/Userland/Libraries/LibCore/EventLoop.h index bdca1565200..a5bbc7bff2a 100644 --- a/Userland/Libraries/LibCore/EventLoop.h +++ b/Userland/Libraries/LibCore/EventLoop.h @@ -68,6 +68,7 @@ public: void add_job(NonnullRefPtr>> job_promise); void deferred_invoke(Function); + void deferred_invoke_if(Function, Function); void wake(); @@ -102,5 +103,5 @@ private: }; void deferred_invoke(Function); - +void deferred_invoke_if(Function, Function); } diff --git a/Userland/Libraries/LibCore/ThreadEventQueue.cpp b/Userland/Libraries/LibCore/ThreadEventQueue.cpp index a6fbe30dccc..959385b26bd 100644 --- a/Userland/Libraries/LibCore/ThreadEventQueue.cpp +++ b/Userland/Libraries/LibCore/ThreadEventQueue.cpp @@ -84,6 +84,7 @@ void ThreadEventQueue::cancel_all_pending_jobs() size_t ThreadEventQueue::process() { decltype(m_private->queued_events) events; + decltype(m_private->queued_events) future_events; { Threading::MutexLocker locker(m_private->mutex); events = move(m_private->queued_events); @@ -105,7 +106,10 @@ size_t ThreadEventQueue::process() break; } } else if (event.type() == Event::Type::DeferredInvoke) { - static_cast(event).m_invokee(); + if (static_cast(*receiver).should_invoke()) + static_cast(event).m_invokee(); + else + future_events.append(move(queued_event)); } else { NonnullRefPtr protector(*receiver); receiver->dispatch_event(event); @@ -115,6 +119,8 @@ size_t ThreadEventQueue::process() { Threading::MutexLocker locker(m_private->mutex); + if (!future_events.is_empty()) + m_private->queued_events.extend(move(future_events)); if (m_private->pending_promises.size() > 30 && !m_private->warned_promise_count) { m_private->warned_promise_count = true; dbgln("ThreadEventQueue::process: Job queue wasn't designed for this load ({} promises)", m_private->pending_promises.size());