فهرست منبع

LibCore+Userland: Implement Core::deferred_invoke

Core::deferred_invoke is a way of executing an action after previously
queued events have been processed. It removes the requirement of
having/being a Core::Object subclass in order to defer invocation
through Core::Object::deferred_invoke.

Core::Object::deferred_invoke now delegates to Core::deferred_invoke.
The version with the Object& argument is still present but will be
removed in the following commits.

This commit additionally fixes a new places where the
DeferredInvocationEvent was dispatched to the event loop directly, and
replaces them with the Core::deferred_invoke equivalent.
sin-ack 3 سال پیش
والد
کامیت
e9121f8b1f

+ 13 - 16
Userland/DevTools/HackStudio/HackStudioWidget.cpp

@@ -793,32 +793,29 @@ void HackStudioWidget::initialize_debugger()
             }
             }
             dbgln("Debugger stopped at source position: {}:{}", source_position.value().file_path, source_position.value().line_number);
             dbgln("Debugger stopped at source position: {}:{}", source_position.value().file_path, source_position.value().line_number);
 
 
-            Core::EventLoop::main().post_event(
-                *window(),
-                make<Core::DeferredInvocationEvent>(
-                    [this, source_position, &regs](auto&) {
-                        m_current_editor_in_execution = get_editor_of_file(source_position.value().file_path);
-                        if (m_current_editor_in_execution)
-                            m_current_editor_in_execution->editor().set_execution_position(source_position.value().line_number - 1);
-                        m_debug_info_widget->update_state(*Debugger::the().session(), regs);
-                        m_debug_info_widget->set_debug_actions_enabled(true);
-                        m_disassembly_widget->update_state(*Debugger::the().session(), regs);
-                        HackStudioWidget::reveal_action_tab(*m_debug_info_widget);
-                    }));
+            deferred_invoke([this, source_position, &regs] {
+                m_current_editor_in_execution = get_editor_of_file(source_position.value().file_path);
+                if (m_current_editor_in_execution)
+                    m_current_editor_in_execution->editor().set_execution_position(source_position.value().line_number - 1);
+                m_debug_info_widget->update_state(*Debugger::the().session(), regs);
+                m_debug_info_widget->set_debug_actions_enabled(true);
+                m_disassembly_widget->update_state(*Debugger::the().session(), regs);
+                HackStudioWidget::reveal_action_tab(*m_debug_info_widget);
+            });
             Core::EventLoop::wake();
             Core::EventLoop::wake();
 
 
             return Debugger::HasControlPassedToUser::Yes;
             return Debugger::HasControlPassedToUser::Yes;
         },
         },
         [this]() {
         [this]() {
-            Core::EventLoop::main().post_event(*window(), make<Core::DeferredInvocationEvent>([this](auto&) {
+            deferred_invoke([this] {
                 m_debug_info_widget->set_debug_actions_enabled(false);
                 m_debug_info_widget->set_debug_actions_enabled(false);
                 if (m_current_editor_in_execution)
                 if (m_current_editor_in_execution)
                     m_current_editor_in_execution->editor().clear_execution_position();
                     m_current_editor_in_execution->editor().clear_execution_position();
-            }));
+            });
             Core::EventLoop::wake();
             Core::EventLoop::wake();
         },
         },
         [this]() {
         [this]() {
-            Core::EventLoop::main().post_event(*window(), make<Core::DeferredInvocationEvent>([this](auto&) {
+            deferred_invoke([this] {
                 m_debug_info_widget->set_debug_actions_enabled(false);
                 m_debug_info_widget->set_debug_actions_enabled(false);
                 if (m_current_editor_in_execution)
                 if (m_current_editor_in_execution)
                     m_current_editor_in_execution->editor().clear_execution_position();
                     m_current_editor_in_execution->editor().clear_execution_position();
@@ -834,7 +831,7 @@ void HackStudioWidget::initialize_debugger()
 
 
                 HackStudioWidget::hide_action_tabs();
                 HackStudioWidget::hide_action_tabs();
                 GUI::MessageBox::show(window(), "Program Exited", "Debugger", GUI::MessageBox::Type::Information);
                 GUI::MessageBox::show(window(), "Program Exited", "Debugger", GUI::MessageBox::Type::Information);
-            }));
+            });
             Core::EventLoop::wake();
             Core::EventLoop::wake();
         });
         });
 }
 }

+ 19 - 0
Userland/Libraries/LibCore/DeferredInvocationContext.h

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018-2020, sin-ack <sin-ack@protonmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibCore/Object.h>
+
+namespace Core {
+
+class DeferredInvocationContext final : public Core::Object {
+    C_OBJECT(DeferredInvocationContext)
+private:
+    DeferredInvocationContext() { }
+};
+
+}

+ 5 - 2
Userland/Libraries/LibCore/Event.h

@@ -10,6 +10,7 @@
 #include <AK/String.h>
 #include <AK/String.h>
 #include <AK/Types.h>
 #include <AK/Types.h>
 #include <AK/WeakPtr.h>
 #include <AK/WeakPtr.h>
+#include <LibCore/DeferredInvocationContext.h>
 #include <LibCore/Forward.h>
 #include <LibCore/Forward.h>
 
 
 namespace Core {
 namespace Core {
@@ -50,14 +51,16 @@ class DeferredInvocationEvent : public Event {
     friend class EventLoop;
     friend class EventLoop;
 
 
 public:
 public:
-    DeferredInvocationEvent(Function<void(Object&)> invokee)
+    DeferredInvocationEvent(NonnullRefPtr<DeferredInvocationContext> context, Function<void()> invokee)
         : Event(Event::Type::DeferredInvoke)
         : Event(Event::Type::DeferredInvoke)
+        , m_context(move(context))
         , m_invokee(move(invokee))
         , m_invokee(move(invokee))
     {
     {
     }
     }
 
 
 private:
 private:
-    Function<void(Object&)> m_invokee;
+    NonnullRefPtr<DeferredInvocationContext> m_context;
+    Function<void()> m_invokee;
 };
 };
 
 
 class TimerEvent final : public Event {
 class TimerEvent final : public Event {

+ 1 - 1
Userland/Libraries/LibCore/EventLoop.cpp

@@ -394,7 +394,7 @@ void EventLoop::pump(WaitMode mode)
             }
             }
         } else if (event.type() == Event::Type::DeferredInvoke) {
         } else if (event.type() == Event::Type::DeferredInvoke) {
             dbgln_if(DEFERRED_INVOKE_DEBUG, "DeferredInvoke: receiver = {}", *receiver);
             dbgln_if(DEFERRED_INVOKE_DEBUG, "DeferredInvoke: receiver = {}", *receiver);
-            static_cast<DeferredInvocationEvent&>(event).m_invokee(*receiver);
+            static_cast<DeferredInvocationEvent&>(event).m_invokee();
         } else {
         } else {
             NonnullRefPtr<Object> protector(*receiver);
             NonnullRefPtr<Object> protector(*receiver);
             receiver->dispatch_event(event);
             receiver->dispatch_event(event);

+ 14 - 0
Userland/Libraries/LibCore/EventLoop.h

@@ -11,9 +11,12 @@
 #include <AK/HashMap.h>
 #include <AK/HashMap.h>
 #include <AK/Noncopyable.h>
 #include <AK/Noncopyable.h>
 #include <AK/NonnullOwnPtr.h>
 #include <AK/NonnullOwnPtr.h>
+#include <AK/NonnullRefPtr.h>
 #include <AK/Time.h>
 #include <AK/Time.h>
 #include <AK/Vector.h>
 #include <AK/Vector.h>
 #include <AK/WeakPtr.h>
 #include <AK/WeakPtr.h>
+#include <LibCore/DeferredInvocationContext.h>
+#include <LibCore/Event.h>
 #include <LibCore/Forward.h>
 #include <LibCore/Forward.h>
 #include <sys/time.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/types.h>
@@ -76,6 +79,12 @@ public:
 
 
     static bool has_been_instantiated();
     static bool has_been_instantiated();
 
 
+    void deferred_invoke(Function<void()> invokee)
+    {
+        auto context = DeferredInvocationContext::construct();
+        post_event(context, make<Core::DeferredInvocationEvent>(context, move(invokee)));
+    }
+
 private:
 private:
     void wait_for_event(WaitMode);
     void wait_for_event(WaitMode);
     Optional<Time> get_next_timer_expiration();
     Optional<Time> get_next_timer_expiration();
@@ -106,4 +115,9 @@ private:
     NonnullOwnPtr<Private> m_private;
     NonnullOwnPtr<Private> m_private;
 };
 };
 
 
+inline void deferred_invoke(Function<void()> invokee)
+{
+    EventLoop::current().deferred_invoke(move(invokee));
+}
+
 }
 }

+ 1 - 0
Userland/Libraries/LibCore/Forward.h

@@ -15,6 +15,7 @@ class ConfigFile;
 class CustomEvent;
 class CustomEvent;
 class DateTime;
 class DateTime;
 class DirIterator;
 class DirIterator;
+class DeferredInvocationContext;
 class ElapsedTimer;
 class ElapsedTimer;
 class Event;
 class Event;
 class EventLoop;
 class EventLoop;

+ 6 - 1
Userland/Libraries/LibCore/Object.cpp

@@ -164,7 +164,12 @@ void Object::dump_tree(int indent)
 
 
 void Object::deferred_invoke(Function<void(Object&)> invokee)
 void Object::deferred_invoke(Function<void(Object&)> invokee)
 {
 {
-    Core::EventLoop::current().post_event(*this, make<Core::DeferredInvocationEvent>(move(invokee)));
+    deferred_invoke([invokee = move(invokee), this] { invokee(*this); });
+}
+
+void Object::deferred_invoke(Function<void()> invokee)
+{
+    Core::deferred_invoke([invokee = move(invokee), strong_this = NonnullRefPtr(*this)] { invokee(); });
 }
 }
 
 
 void Object::save_to(JsonObject& json)
 void Object::save_to(JsonObject& json)

+ 1 - 0
Userland/Libraries/LibCore/Object.h

@@ -130,6 +130,7 @@ public:
     void dump_tree(int indent = 0);
     void dump_tree(int indent = 0);
 
 
     void deferred_invoke(Function<void(Object&)>);
     void deferred_invoke(Function<void(Object&)>);
+    void deferred_invoke(Function<void()>);
 
 
     void save_to(JsonObject&);
     void save_to(JsonObject&);
 
 

+ 3 - 3
Userland/Libraries/LibThreading/BackgroundAction.h

@@ -66,10 +66,10 @@ private:
         enqueue_work([this] {
         enqueue_work([this] {
             m_result = m_action(*this);
             m_result = m_action(*this);
             if (m_on_complete) {
             if (m_on_complete) {
-                Core::EventLoop::current().post_event(*this, make<Core::DeferredInvocationEvent>([this](auto&) {
+                deferred_invoke([this] {
                     m_on_complete(m_result.release_value());
                     m_on_complete(m_result.release_value());
-                    this->remove_from_parent();
-                }));
+                    remove_from_parent();
+                });
                 Core::EventLoop::wake();
                 Core::EventLoop::wake();
             } else {
             } else {
                 this->remove_from_parent();
                 this->remove_from_parent();