<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[191878] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/191878">191878</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2015-11-02 00:41:02 -0800 (Mon, 02 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[GTK] Use RunLoop in WorkQueue implementation
https://bugs.webkit.org/show_bug.cgi?id=150770

Reviewed by Darin Adler.

Source/WebKit2:

* Platform/IPC/unix/ConnectionUnix.cpp:
(IPC::Connection::open): Get the main context from the WorkQueue Runloop.

Source/WTF:

Instead of using GMainLoop directly. RunLoop already abstracts the
GMainLoop details and uses persistent sources making it more efficient.
For the dispatchAfter implementation we use a helper context class
and a GSource directly, since we are going to get rid of delete on
destroy GMainLoop soon and this is the only place where we still
use them.

* wtf/RunLoop.h:
(WTF::RunLoop::mainContext): Return the GMainContext.
* wtf/WorkQueue.h:
* wtf/glib/WorkQueueGLib.cpp:
(WTF::WorkQueue::platformInitialize): The RunLoop needs to be
created in the worker thread now, so we now use a mutex to wait
until the thread has started and the RunLoop has been created.
(WTF::WorkQueue::platformInvalidate): Stop the RunLoop and wait
until the thread finishes.
(WTF::WorkQueue::dispatch): Use RunLoop::dispatch().
(WTF::DispatchAfterContext::DispatchAfterContext):
(WTF::DispatchAfterContext::~DispatchAfterContext):
(WTF::DispatchAfterContext::dispatch):
(WTF::WorkQueue::dispatchAfter):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfRunLooph">trunk/Source/WTF/wtf/RunLoop.h</a></li>
<li><a href="#trunkSourceWTFwtfWorkQueueh">trunk/Source/WTF/wtf/WorkQueue.h</a></li>
<li><a href="#trunkSourceWTFwtfglibWorkQueueGLibcpp">trunk/Source/WTF/wtf/glib/WorkQueueGLib.cpp</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformIPCunixConnectionUnixcpp">trunk/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (191877 => 191878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2015-11-02 06:52:50 UTC (rev 191877)
+++ trunk/Source/WTF/ChangeLog        2015-11-02 08:41:02 UTC (rev 191878)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2015-11-01  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Use RunLoop in WorkQueue implementation
+        https://bugs.webkit.org/show_bug.cgi?id=150770
+
+        Reviewed by Darin Adler.
+
+        Instead of using GMainLoop directly. RunLoop already abstracts the
+        GMainLoop details and uses persistent sources making it more efficient.
+        For the dispatchAfter implementation we use a helper context class
+        and a GSource directly, since we are going to get rid of delete on
+        destroy GMainLoop soon and this is the only place where we still
+        use them.
+
+        * wtf/RunLoop.h:
+        (WTF::RunLoop::mainContext): Return the GMainContext.
+        * wtf/WorkQueue.h:
+        * wtf/glib/WorkQueueGLib.cpp:
+        (WTF::WorkQueue::platformInitialize): The RunLoop needs to be
+        created in the worker thread now, so we now use a mutex to wait
+        until the thread has started and the RunLoop has been created.
+        (WTF::WorkQueue::platformInvalidate): Stop the RunLoop and wait
+        until the thread finishes.
+        (WTF::WorkQueue::dispatch): Use RunLoop::dispatch().
+        (WTF::DispatchAfterContext::DispatchAfterContext):
+        (WTF::DispatchAfterContext::~DispatchAfterContext):
+        (WTF::DispatchAfterContext::dispatch):
+        (WTF::WorkQueue::dispatchAfter):
+
</ins><span class="cx"> 2015-11-01  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Support Generator Syntax
</span></span></pre></div>
<a id="trunkSourceWTFwtfRunLooph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/RunLoop.h (191877 => 191878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/RunLoop.h        2015-11-02 06:52:50 UTC (rev 191877)
+++ trunk/Source/WTF/wtf/RunLoop.h        2015-11-02 08:41:02 UTC (rev 191878)
</span><span class="lines">@@ -67,7 +67,11 @@
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     WTF_EXPORT_PRIVATE void runForDuration(double duration);
</span><span class="cx"> #endif
</span><del>-    
</del><ins>+
+#if USE(GLIB) &amp;&amp; !PLATFORM(EFL)
+    WTF_EXPORT_PRIVATE GMainContext* mainContext() const { return m_mainContext.get(); }
+#endif
+
</ins><span class="cx">     class TimerBase {
</span><span class="cx">         friend class RunLoop;
</span><span class="cx">     public:
</span></span></pre></div>
<a id="trunkSourceWTFwtfWorkQueueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/WorkQueue.h (191877 => 191878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/WorkQueue.h        2015-11-02 06:52:50 UTC (rev 191877)
+++ trunk/Source/WTF/wtf/WorkQueue.h        2015-11-02 08:41:02 UTC (rev 191878)
</span><span class="lines">@@ -39,7 +39,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(GTK)
</span><del>-#include &lt;wtf/glib/GMainLoopSource.h&gt;
</del><ins>+#include &lt;wtf/Condition.h&gt;
+#include &lt;wtf/RunLoop.h&gt;
</ins><span class="cx"> #include &lt;wtf/glib/GRefPtr.h&gt;
</span><span class="cx"> #elif PLATFORM(EFL)
</span><span class="cx"> #include &lt;DispatchQueueEfl.h&gt;
</span><span class="lines">@@ -74,7 +75,7 @@
</span><span class="cx">     WTF_EXPORT_PRIVATE static void concurrentApply(size_t iterations, const std::function&lt;void (size_t index)&gt;&amp;);
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(GTK)
</span><del>-    GMainContext* mainContext() const { return m_eventContext.get(); }
</del><ins>+    RunLoop&amp; runLoop() const { return *m_runLoop; }
</ins><span class="cx"> #elif PLATFORM(EFL)
</span><span class="cx">     void registerSocketEventHandler(int, std::function&lt;void ()&gt;);
</span><span class="cx">     void unregisterSocketEventHandler(int);
</span><span class="lines">@@ -103,8 +104,11 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(GTK)
</span><span class="cx">     ThreadIdentifier m_workQueueThread;
</span><del>-    GRefPtr&lt;GMainContext&gt; m_eventContext;
-    GRefPtr&lt;GMainLoop&gt; m_eventLoop;
</del><ins>+    Lock m_initializeRunLoopConditionMutex;
+    Condition m_initializeRunLoopCondition;
+    RunLoop* m_runLoop;
+    Lock m_terminateRunLoopConditionMutex;
+    Condition m_terminateRunLoopCondition;
</ins><span class="cx"> #elif PLATFORM(EFL)
</span><span class="cx">     RefPtr&lt;DispatchQueue&gt; m_dispatchQueue;
</span><span class="cx"> #elif OS(DARWIN)
</span></span></pre></div>
<a id="trunkSourceWTFwtfglibWorkQueueGLibcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/glib/WorkQueueGLib.cpp (191877 => 191878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/glib/WorkQueueGLib.cpp        2015-11-02 06:52:50 UTC (rev 191877)
+++ trunk/Source/WTF/wtf/glib/WorkQueueGLib.cpp        2015-11-02 08:41:02 UTC (rev 191878)
</span><span class="lines">@@ -37,11 +37,6 @@
</span><span class="cx"> 
</span><span class="cx"> void WorkQueue::platformInitialize(const char* name, Type, QOS)
</span><span class="cx"> {
</span><del>-    m_eventContext = adoptGRef(g_main_context_new());
-    ASSERT(m_eventContext);
-    m_eventLoop = adoptGRef(g_main_loop_new(m_eventContext.get(), FALSE));
-    ASSERT(m_eventLoop);
-
</del><span class="cx">     // This name can be com.apple.WebKit.ProcessLauncher or com.apple.CoreIPC.ReceiveQueue.
</span><span class="cx">     // We are using those names for the thread name, but both are longer than 31 characters,
</span><span class="cx">     // which is the limit of Visual Studio for thread names.
</span><span class="lines">@@ -55,47 +50,80 @@
</span><span class="cx">     if (strlen(threadName) &gt; kVisualStudioThreadNameLimit)
</span><span class="cx">         threadName += strlen(threadName) - kVisualStudioThreadNameLimit;
</span><span class="cx"> 
</span><del>-    GRefPtr&lt;GMainLoop&gt; eventLoop(m_eventLoop.get());
-    m_workQueueThread = createThread(threadName, [eventLoop] {
-        g_main_context_push_thread_default(g_main_loop_get_context(eventLoop.get()));
-        g_main_loop_run(eventLoop.get());
</del><ins>+    LockHolder locker(m_initializeRunLoopConditionMutex);
+    m_workQueueThread = createThread(threadName, [this] {
+        {
+            LockHolder locker(m_initializeRunLoopConditionMutex);
+            m_runLoop = &amp;RunLoop::current();
+            m_initializeRunLoopCondition.notifyOne();
+        }
+        m_runLoop-&gt;run();
+        {
+            LockHolder locker(m_terminateRunLoopConditionMutex);
+            m_runLoop = nullptr;
+            m_terminateRunLoopCondition.notifyOne();
+        }
</ins><span class="cx">     });
</span><ins>+    m_initializeRunLoopCondition.wait(m_initializeRunLoopConditionMutex);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WorkQueue::platformInvalidate()
</span><span class="cx"> {
</span><ins>+    {
+        LockHolder locker(m_terminateRunLoopConditionMutex);
+        if (m_runLoop) {
+            m_runLoop-&gt;stop();
+            m_terminateRunLoopCondition.wait(m_terminateRunLoopConditionMutex);
+        }
+    }
+
</ins><span class="cx">     if (m_workQueueThread) {
</span><span class="cx">         detachThread(m_workQueueThread);
</span><span class="cx">         m_workQueueThread = 0;
</span><span class="cx">     }
</span><del>-
-    if (m_eventLoop) {
-        if (g_main_loop_is_running(m_eventLoop.get()))
-            g_main_loop_quit(m_eventLoop.get());
-        else {
-            // The thread hasn't started yet, so schedule a main loop quit to ensure the thread finishes.
-            GMainLoop* eventLoop = m_eventLoop.get();
-            GMainLoopSource::scheduleAndDeleteOnDestroy(&quot;[WebKit] WorkQueue quit main loop&quot;, [eventLoop] { g_main_loop_quit(eventLoop); },
-                G_PRIORITY_HIGH, nullptr, m_eventContext.get());
-        }
-        m_eventLoop = nullptr;
-    }
-
-    m_eventContext = nullptr;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WorkQueue::dispatch(std::function&lt;void ()&gt; function)
</span><span class="cx"> {
</span><del>-    ref();
-    GMainLoopSource::scheduleAndDeleteOnDestroy(&quot;[WebKit] WorkQueue::dispatch&quot;, WTF::move(function), G_PRIORITY_DEFAULT,
-        [this] { deref(); }, m_eventContext.get());
</del><ins>+    RefPtr&lt;WorkQueue&gt; protector(this);
+    m_runLoop-&gt;dispatch([protector, function] { function(); });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+class DispatchAfterContext {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    DispatchAfterContext(WorkQueue&amp; queue, std::function&lt;void ()&gt; function)
+        : m_queue(&amp;queue)
+        , m_function(WTF::move(function))
+    {
+    }
+
+    ~DispatchAfterContext()
+    {
+    }
+
+    void dispatch()
+    {
+        m_function();
+    }
+
+private:
+    RefPtr&lt;WorkQueue&gt; m_queue;
+    std::function&lt;void ()&gt; m_function;
+};
+
</ins><span class="cx"> void WorkQueue::dispatchAfter(std::chrono::nanoseconds duration, std::function&lt;void ()&gt; function)
</span><span class="cx"> {
</span><del>-    ref();
-    GMainLoopSource::scheduleAfterDelayAndDeleteOnDestroy(&quot;[WebKit] WorkQueue::dispatchAfter&quot;, WTF::move(function),
-        std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(duration), G_PRIORITY_DEFAULT, [this] { deref(); }, m_eventContext.get());
</del><ins>+    GRefPtr&lt;GSource&gt; source = adoptGRef(g_timeout_source_new(std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(duration).count()));
+    g_source_set_name(source.get(), &quot;[WebKit] WorkQueue dispatchAfter&quot;);
+
+    std::unique_ptr&lt;DispatchAfterContext&gt; context = std::make_unique&lt;DispatchAfterContext&gt;(*this, WTF::move(function));
+    g_source_set_callback(source.get(), [](gpointer userData) -&gt; gboolean {
+        std::unique_ptr&lt;DispatchAfterContext&gt; context(static_cast&lt;DispatchAfterContext*&gt;(userData));
+        context-&gt;dispatch();
+        return G_SOURCE_REMOVE;
+    }, context.release(), nullptr);
+    g_source_attach(source.get(), m_runLoop-&gt;mainContext());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (191877 => 191878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-11-02 06:52:50 UTC (rev 191877)
+++ trunk/Source/WebKit2/ChangeLog        2015-11-02 08:41:02 UTC (rev 191878)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-11-01  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Use RunLoop in WorkQueue implementation
+        https://bugs.webkit.org/show_bug.cgi?id=150770
+
+        Reviewed by Darin Adler.
+
+        * Platform/IPC/unix/ConnectionUnix.cpp:
+        (IPC::Connection::open): Get the main context from the WorkQueue Runloop.
+
</ins><span class="cx"> 2015-11-01  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Support Generator Syntax
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformIPCunixConnectionUnixcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp (191877 => 191878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp        2015-11-02 06:52:50 UTC (rev 191877)
+++ trunk/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp        2015-11-02 08:41:02 UTC (rev 191878)
</span><span class="lines">@@ -390,7 +390,7 @@
</span><span class="cx"> 
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><span class="cx">         return GMainLoopSource::Stop;
</span><del>-    }, socket.get(), G_IO_IN, nullptr, m_connectionQueue-&gt;mainContext());
</del><ins>+    }, socket.get(), G_IO_IN, nullptr, m_connectionQueue-&gt;runLoop().mainContext());
</ins><span class="cx"> #elif PLATFORM(EFL)
</span><span class="cx">     m_connectionQueue-&gt;registerSocketEventHandler(m_socketDescriptor,
</span><span class="cx">         [protectedThis] {
</span></span></pre>
</div>
</div>

</body>
</html>