LibCore: Add Core::deferred_invoke_if(F, Condition)

This will invoke the function F only if the provided Condition is met,
otherwise the execution of the function F will be further deferred.
This commit is contained in:
Ali Mohammad Pur 2024-05-08 20:08:18 +02:00 committed by Andreas Kling
parent 68a1a78a1a
commit a362c37c8b
Notes: sideshowbarker 2024-07-17 03:05:16 +09:00
4 changed files with 34 additions and 3 deletions

View file

@ -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<bool()> condition)
: m_condition(move(condition))
{
}
Function<bool()> m_condition;
};
}

View file

@ -156,11 +156,22 @@ void EventLoop::deferred_invoke(Function<void()> invokee)
post_event(context, make<Core::DeferredInvocationEvent>(context, move(invokee)));
}
void EventLoop::deferred_invoke_if(Function<void()> invokee, Function<bool()> condition)
{
auto context = DeferredInvocationContext::construct(move(condition));
post_event(context, make<Core::DeferredInvocationEvent>(context, move(invokee)));
}
void deferred_invoke(Function<void()> invokee)
{
EventLoop::current().deferred_invoke(move(invokee));
}
void deferred_invoke_if(Function<void()> invokee, Function<bool()> condition)
{
EventLoop::current().deferred_invoke_if(move(invokee), move(condition));
}
bool EventLoop::was_exit_requested() const
{
return m_impl->was_exit_requested();

View file

@ -68,6 +68,7 @@ public:
void add_job(NonnullRefPtr<Promise<NonnullRefPtr<EventReceiver>>> job_promise);
void deferred_invoke(Function<void()>);
void deferred_invoke_if(Function<void()>, Function<bool()>);
void wake();
@ -102,5 +103,5 @@ private:
};
void deferred_invoke(Function<void()>);
void deferred_invoke_if(Function<void()>, Function<bool()>);
}

View file

@ -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<DeferredInvocationEvent&>(event).m_invokee();
if (static_cast<DeferredInvocationContext&>(*receiver).should_invoke())
static_cast<DeferredInvocationEvent&>(event).m_invokee();
else
future_events.append(move(queued_event));
} else {
NonnullRefPtr<EventReceiver> 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());