[GTK] Use a persistent main loop source in RunLoop glib implementation
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Oct 2015 11:28:14 +0000 (11:28 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Oct 2015 11:28:14 +0000 (11:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=150590

Reviewed by Žan Doberšek.

Source/WebKit2:

Use RunLoop::dispatch() instead of
GMainLoopSource::scheduleAndDeleteOnDestroy in a couple of simple
cases.

* NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp:
(WebKit::NetworkCache::runTaskInQueue):
* UIProcess/gtk/DragAndDropHandler.cpp:
(WebKit::DragAndDropHandler::dragLeave):

Source/WTF:

It's more efficient than creating and destroying a new source for
every dispatch and it simplifies the code.

* wtf/RunLoop.h:
* wtf/glib/MainThreadGLib.cpp:
(WTF::scheduleDispatchFunctionsOnMainThread): Use
RunLoop::dispatch() instead of GMainLoopSource::scheduleAndDeleteOnDestroy().
* wtf/glib/RunLoopGLib.cpp:
(WTF::RunLoop::RunLoop): Create and setup the persistent source.
(WTF::RunLoop::~RunLoop): Destroy the persistent source.
(WTF::RunLoop::stop): Stop the persistent source before stopping
the main loop.
(WTF::RunLoop::wakeUp): Make the persistent source active. We
no longer need to explicitly wakeup the context.
(WTF::RunLoop::TimerBase::TimerBase): Create and setup the
persistent source.
(WTF::RunLoop::TimerBase::~TimerBase): Destroy the persistent source.
(WTF::RunLoop::TimerBase::updateReadyTime): Set the ready time
according to the fire interval.
(WTF::RunLoop::TimerBase::start): Make the persistent source active.
(WTF::RunLoop::TimerBase::stop): Stop the persistent source.
(WTF::RunLoop::TimerBase::isActive): Return whether the
persistent source is active.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@191786 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WTF/ChangeLog
Source/WTF/wtf/RunLoop.h
Source/WTF/wtf/glib/MainThreadGLib.cpp
Source/WTF/wtf/glib/RunLoopGLib.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp
Source/WebKit2/UIProcess/gtk/DragAndDropHandler.cpp

index 4797fc7dbd9a3a9600bc889a559eecfba45972cf..748f2fe855c6ecdad81a1f3f96f7f3497045a205 100644 (file)
@@ -1,3 +1,34 @@
+2015-10-29  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Use a persistent main loop source in RunLoop glib implementation
+        https://bugs.webkit.org/show_bug.cgi?id=150590
+
+        Reviewed by Žan Doberšek.
+
+        It's more efficient than creating and destroying a new source for
+        every dispatch and it simplifies the code.
+
+        * wtf/RunLoop.h:
+        * wtf/glib/MainThreadGLib.cpp:
+        (WTF::scheduleDispatchFunctionsOnMainThread): Use
+        RunLoop::dispatch() instead of GMainLoopSource::scheduleAndDeleteOnDestroy().
+        * wtf/glib/RunLoopGLib.cpp:
+        (WTF::RunLoop::RunLoop): Create and setup the persistent source.
+        (WTF::RunLoop::~RunLoop): Destroy the persistent source.
+        (WTF::RunLoop::stop): Stop the persistent source before stopping
+        the main loop.
+        (WTF::RunLoop::wakeUp): Make the persistent source active. We
+        no longer need to explicitly wakeup the context.
+        (WTF::RunLoop::TimerBase::TimerBase): Create and setup the
+        persistent source.
+        (WTF::RunLoop::TimerBase::~TimerBase): Destroy the persistent source.
+        (WTF::RunLoop::TimerBase::updateReadyTime): Set the ready time
+        according to the fire interval.
+        (WTF::RunLoop::TimerBase::start): Make the persistent source active.
+        (WTF::RunLoop::TimerBase::stop): Stop the persistent source.
+        (WTF::RunLoop::TimerBase::isActive): Return whether the
+        persistent source is active.
+
 2015-10-30  Philippe Normand  <pnormand@igalia.com>
 
         [GTK][Mac] fix WTF build
index 6f30236b34c2816a8158d5ef7e7e5a09e8d54a0d..9b159e6823abedb867a10032377d8053c7db975f 100644 (file)
@@ -36,7 +36,7 @@
 #include <wtf/Threading.h>
 
 #if USE(GLIB)
-#include <wtf/glib/GMainLoopSource.h>
+#include <wtf/glib/GRefPtr.h>
 #endif
 
 #if PLATFORM(EFL)
@@ -100,7 +100,10 @@ public:
         Ecore_Timer* m_timer;
         bool m_isRepeating;
 #elif USE(GLIB)
-        GMainLoopSource m_timerSource;
+        void updateReadyTime();
+        GRefPtr<GSource> m_source;
+        bool m_isRepeating { false };
+        std::chrono::microseconds m_fireInterval { 0 };
 #endif
     };
 
@@ -155,11 +158,9 @@ private:
 
     static void wakeUpEvent(void* data, void*, unsigned);
 #elif USE(GLIB)
-public:
-    static gboolean queueWork(RunLoop*);
-private:
     GRefPtr<GMainContext> m_mainContext;
     Vector<GRefPtr<GMainLoop>> m_mainLoops;
+    GRefPtr<GSource> m_source;
 #endif
 };
 
index 649a9a502bed6474696a60031b6ff4b6c9b43a7d..d2e121fb927f86b0140115be33aa77c7d6058779 100644 (file)
@@ -30,7 +30,7 @@
 #include "config.h"
 #include "MainThread.h"
 
-#include <wtf/glib/GMainLoopSource.h>
+#include <wtf/RunLoop.h>
 
 namespace WTF {
 
@@ -40,7 +40,7 @@ void initializeMainThreadPlatform()
 
 void scheduleDispatchFunctionsOnMainThread()
 {
-    GMainLoopSource::scheduleAndDeleteOnDestroy("[WebKit] dispatchFunctionsFromMainThread", std::function<void()>(dispatchFunctionsFromMainThread));
+    RunLoop::main().dispatch(std::function<void()>(dispatchFunctionsFromMainThread));
 }
 
 } // namespace WTF
index 7dc407566082a238baf96108762eec242f6eb98b..c5e8ffd3acb1ca4d5249706afa2570041068004c 100644 (file)
 
 namespace WTF {
 
+static GSourceFuncs runLoopSourceFunctions = {
+    nullptr, // prepare
+    nullptr, // check
+    // dispatch
+    [](GSource* source, GSourceFunc callback, gpointer userData) -> gboolean
+    {
+        if (g_source_get_ready_time(source) == -1)
+            return G_SOURCE_CONTINUE;
+        g_source_set_ready_time(source, -1);
+        return callback(userData);
+    },
+    nullptr, // finalize
+    nullptr, // closure_callback
+    nullptr, // closure_marshall
+};
+
 RunLoop::RunLoop()
 {
     m_mainContext = g_main_context_get_thread_default();
@@ -42,10 +58,21 @@ RunLoop::RunLoop()
     GRefPtr<GMainLoop> innermostLoop = adoptGRef(g_main_loop_new(m_mainContext.get(), FALSE));
     ASSERT(innermostLoop);
     m_mainLoops.append(innermostLoop);
+
+    m_source = adoptGRef(g_source_new(&runLoopSourceFunctions, sizeof(GSource)));
+    g_source_set_name(m_source.get(), "[WebKit] RunLoop work");
+    g_source_set_can_recurse(m_source.get(), TRUE);
+    g_source_set_callback(m_source.get(), [](gpointer userData) -> gboolean {
+        static_cast<RunLoop*>(userData)->performWork();
+        return G_SOURCE_CONTINUE;
+    }, this, nullptr);
+    g_source_attach(m_source.get(), m_mainContext.get());
 }
 
 RunLoop::~RunLoop()
 {
+    g_source_destroy(m_source.get());
+
     for (int i = m_mainLoops.size() - 1; i >= 0; --i) {
         if (!g_main_loop_is_running(m_mainLoops[i].get()))
             continue;
@@ -91,37 +118,49 @@ void RunLoop::stop()
 
 void RunLoop::wakeUp()
 {
-    RefPtr<RunLoop> runLoop(this);
-    GMainLoopSource::scheduleAndDeleteOnDestroy("[WebKit] RunLoop work", std::function<void()>([runLoop] {
-        runLoop->performWork();
-    }), G_PRIORITY_DEFAULT, nullptr, m_mainContext.get());
-    g_main_context_wakeup(m_mainContext.get());
+    g_source_set_ready_time(m_source.get(), g_get_monotonic_time());
 }
 
 RunLoop::TimerBase::TimerBase(RunLoop& runLoop)
     : m_runLoop(runLoop)
+    , m_source(adoptGRef(g_source_new(&runLoopSourceFunctions, sizeof(GSource))))
 {
+    g_source_set_name(m_source.get(), "[WebKit] RunLoop::Timer work");
+    g_source_set_callback(m_source.get(), [](gpointer userData) -> gboolean {
+        RunLoop::TimerBase* timer = static_cast<RunLoop::TimerBase*>(userData);
+        timer->fired();
+        if (timer->m_isRepeating)
+            timer->updateReadyTime();
+        return G_SOURCE_CONTINUE;
+    }, this, nullptr);
+    g_source_attach(m_source.get(), m_runLoop.m_mainContext.get());
 }
 
 RunLoop::TimerBase::~TimerBase()
 {
-    stop();
+    g_source_destroy(m_source.get());
+}
+
+void RunLoop::TimerBase::updateReadyTime()
+{
+    g_source_set_ready_time(m_source.get(), m_fireInterval.count() ? g_get_monotonic_time() + m_fireInterval.count() : 0);
 }
 
 void RunLoop::TimerBase::start(double fireInterval, bool repeat)
 {
-    m_timerSource.scheduleAfterDelay("[WebKit] RunLoop::Timer", std::function<bool ()>([this, repeat] { fired(); return repeat; }),
-        std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::duration<double>(fireInterval)), G_PRIORITY_DEFAULT, nullptr, m_runLoop.m_mainContext.get());
+    m_fireInterval = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(fireInterval));
+    m_isRepeating = repeat;
+    updateReadyTime();
 }
 
 void RunLoop::TimerBase::stop()
 {
-    m_timerSource.cancel();
+    g_source_set_ready_time(m_source.get(), -1);
 }
 
 bool RunLoop::TimerBase::isActive() const
 {
-    return m_timerSource.isScheduled();
+    return g_source_get_ready_time(m_source.get()) != -1;
 }
 
 } // namespace WTF
index b49231cfeca285dffc721bb4a5b88f9a19a4a54f..2fed6825510988f471e42b27356b71ca8ac7597a 100644 (file)
@@ -1,3 +1,19 @@
+2015-10-29  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Use a persistent main loop source in RunLoop glib implementation
+        https://bugs.webkit.org/show_bug.cgi?id=150590
+
+        Reviewed by Žan Doberšek.
+
+        Use RunLoop::dispatch() instead of
+        GMainLoopSource::scheduleAndDeleteOnDestroy in a couple of simple
+        cases.
+
+        * NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp:
+        (WebKit::NetworkCache::runTaskInQueue):
+        * UIProcess/gtk/DragAndDropHandler.cpp:
+        (WebKit::DragAndDropHandler::dragLeave):
+
 2015-10-29  Alex Christensen  <achristensen@webkit.org>
 
         Make WebCore a framework in Mac CMake build
index 5bc07c797ab08a5773dd5628a4fb6ad1668046e7..37a536ad9b8fd31b1c4069af7c4e52d6a4bfe378 100644 (file)
@@ -30,8 +30,7 @@
 
 #include "NetworkCacheFileSystem.h"
 #include <wtf/MainThread.h>
-#include <wtf/glib/GMainLoopSource.h>
-#include <wtf/glib/GMutexLocker.h>
+#include <wtf/RunLoop.h>
 #include <wtf/glib/GUniquePtr.h>
 
 namespace WebKit {
@@ -78,7 +77,7 @@ static inline void runTaskInQueue(std::function<void ()> task, WorkQueue* queue)
     }
 
     // Using nullptr as queue submits the result to the main context.
-    GMainLoopSource::scheduleAndDeleteOnDestroy("[WebKit] IOChannel task", WTF::move(task));
+    RunLoop::main().dispatch(WTF::move(task));
 }
 
 static void fillDataFromReadBuffer(SoupBuffer* readBuffer, size_t size, Data& data)
index 304b6be0d0bcc0da27079e8b4b1b7211caad344e..113f868a3a696c4bee7ecd19ad9da4baec3c9574 100644 (file)
@@ -35,7 +35,7 @@
 #include <WebCore/GtkUtilities.h>
 #include <WebCore/PasteboardHelper.h>
 #include <gtk/gtk.h>
-#include <wtf/glib/GMainLoopSource.h>
+#include <wtf/RunLoop.h>
 #include <wtf/glib/GUniquePtr.h>
 
 using namespace WebCore;
@@ -221,7 +221,7 @@ void DragAndDropHandler::dragLeave(GdkDragContext* context)
     // During a drop GTK+ will fire a drag-leave signal right before firing
     // the drag-drop signal. We want the actions for drag-leave to happen after
     // those for drag-drop, so schedule them to happen asynchronously here.
-    GMainLoopSource::scheduleAndDeleteOnDestroy("[WebKit] handleDragLeaveLater", [this, droppingContext]() {
+    RunLoop::main().dispatch([this, droppingContext]() {
         auto it = m_droppingContexts.find(droppingContext->gdkContext);
         if (it == m_droppingContexts.end())
             return;