Changeset 169444 in webkit


Ignore:
Timestamp:
May 29, 2014 3:33:02 AM (10 years ago)
Author:
Carlos Garcia Campos
Message:

[GTK] Use GMainLoopSource for idle and timeout sources in WebKit2
https://bugs.webkit.org/show_bug.cgi?id=130081

Reviewed by Martin Robinson.

  • Platform/WorkQueue.h:
  • Platform/gtk/WorkQueueGtk.cpp:

(WorkQueue::registerSocketEventHandler): Stop pretending it's
possible to register a socket event handler for more than one
descriptor.
(WorkQueue::unregisterSocketEventHandler):
(WorkQueue::dispatch):
(WorkQueue::dispatchAfter):

  • Shared/Downloads/soup/DownloadSoup.cpp:

(WebKit::DownloadClient::DownloadClient):
(WebKit::DownloadClient::~DownloadClient):
(WebKit::DownloadClient::didReceiveData):
(WebKit::DownloadClient::handleResponse):
(WebKit::DownloadClient::handleResponseLater):

  • UIProcess/Plugins/gtk/PluginInfoCache.cpp:

(WebKit::PluginInfoCache::PluginInfoCache):
(WebKit::PluginInfoCache::~PluginInfoCache):
(WebKit::PluginInfoCache::saveToFile):
(WebKit::PluginInfoCache::updatePluginInfo):

  • UIProcess/Plugins/gtk/PluginInfoCache.h:
  • WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp:

(WebKit::LayerTreeHostGtk::LayerTreeHostGtk):
(WebKit::LayerTreeHostGtk::layerFlushTimerFired):
(WebKit::LayerTreeHostGtk::scheduleLayerFlush):
(WebKit::LayerTreeHostGtk::cancelPendingLayerFlush):

  • WebProcess/WebPage/gtk/LayerTreeHostGtk.h:
Location:
trunk/Source/WebKit2
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r169439 r169444  
     12014-05-28  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK] Use GMainLoopSource for idle and timeout sources in WebKit2
     4        https://bugs.webkit.org/show_bug.cgi?id=130081
     5
     6        Reviewed by Martin Robinson.
     7
     8        * Platform/WorkQueue.h:
     9        * Platform/gtk/WorkQueueGtk.cpp:
     10        (WorkQueue::registerSocketEventHandler): Stop pretending it's
     11        possible to register a socket event handler for more than one
     12        descriptor.
     13        (WorkQueue::unregisterSocketEventHandler):
     14        (WorkQueue::dispatch):
     15        (WorkQueue::dispatchAfter):
     16        * Shared/Downloads/soup/DownloadSoup.cpp:
     17        (WebKit::DownloadClient::DownloadClient):
     18        (WebKit::DownloadClient::~DownloadClient):
     19        (WebKit::DownloadClient::didReceiveData):
     20        (WebKit::DownloadClient::handleResponse):
     21        (WebKit::DownloadClient::handleResponseLater):
     22        * UIProcess/Plugins/gtk/PluginInfoCache.cpp:
     23        (WebKit::PluginInfoCache::PluginInfoCache):
     24        (WebKit::PluginInfoCache::~PluginInfoCache):
     25        (WebKit::PluginInfoCache::saveToFile):
     26        (WebKit::PluginInfoCache::updatePluginInfo):
     27        * UIProcess/Plugins/gtk/PluginInfoCache.h:
     28        * WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp:
     29        (WebKit::LayerTreeHostGtk::LayerTreeHostGtk):
     30        (WebKit::LayerTreeHostGtk::layerFlushTimerFired):
     31        (WebKit::LayerTreeHostGtk::scheduleLayerFlush):
     32        (WebKit::LayerTreeHostGtk::cancelPendingLayerFlush):
     33        * WebProcess/WebPage/gtk/LayerTreeHostGtk.h:
     34
    1352014-05-28  Gavin Barraclough  <baraclough@apple.com>
    236
  • trunk/Source/WebKit2/Platform/WorkQueue.h

    r169424 r169444  
    4646
    4747#if PLATFORM(GTK)
     48#include <wtf/gobject/GMainLoopSource.h>
    4849#include <wtf/gobject/GRefPtr.h>
    49 typedef gboolean (*GSourceFunc) (gpointer data);
    5050#elif PLATFORM(EFL)
    5151#include <DispatchQueueEfl.h>
     
    8080    dispatch_queue_t m_dispatchQueue;
    8181#elif PLATFORM(GTK)
    82     class EventSource;
    83     class SocketEventSource;
    84 
    8582    static void startWorkQueueThread(WorkQueue*);
    8683    void workQueueThreadBody();
    87     void dispatchOnSource(GSource*, std::function<void ()>, GSourceFunc);
    8884
    8985    ThreadIdentifier m_workQueueThread;
     
    9187    Mutex m_eventLoopLock;
    9288    GRefPtr<GMainLoop> m_eventLoop;
    93     Mutex m_eventSourcesLock;
    94     HashMap<int, Vector<SocketEventSource*>> m_eventSources;
     89    GMainLoopSource m_socketEventSource;
    9590#elif PLATFORM(EFL)
    9691    RefPtr<DispatchQueue> m_dispatchQueue;
  • trunk/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp

    r169424 r169444  
    3030
    3131#include <gio/gio.h>
    32 #include <glib.h>
    33 #include <wtf/gobject/GRefPtr.h>
    3432
    35 // WorkQueue::EventSource
    36 class WorkQueue::EventSource {
    37 public:
    38     EventSource(std::function<void()> function, WorkQueue* workQueue)
    39         : m_function(std::move(function))
    40         , m_workQueue(workQueue)
    41     {
    42         ASSERT(workQueue);
    43     }
    44 
    45     virtual ~EventSource() { }
    46 
    47     void performWork()
    48     {
    49         m_function();
    50     }
    51 
    52     static gboolean performWorkOnce(EventSource* eventSource)
    53     {
    54         ASSERT(eventSource);
    55         eventSource->performWork();
    56         return FALSE;
    57     }
    58 
    59     static void deleteEventSource(EventSource* eventSource)
    60     {
    61         ASSERT(eventSource);
    62         delete eventSource;
    63     }
    64 
    65 private:
    66     std::function<void ()> m_function;
    67     RefPtr<WorkQueue> m_workQueue;
    68 };
    69 
    70 class WorkQueue::SocketEventSource : public WorkQueue::EventSource {
    71 public:
    72     SocketEventSource(std::function<void ()> function, WorkQueue* workQueue, GCancellable* cancellable, std::function<void ()> closeFunction)
    73         : EventSource(std::move(function), workQueue)
    74         , m_cancellable(cancellable)
    75         , m_closeFunction(std::move(closeFunction))
    76     {
    77         ASSERT(cancellable);
    78     }
    79 
    80     void cancel()
    81     {
    82         g_cancellable_cancel(m_cancellable);
    83     }
    84 
    85     void didClose()
    86     {
    87         m_closeFunction();
    88     }
    89 
    90     bool isCancelled() const
    91     {
    92         return g_cancellable_is_cancelled(m_cancellable);
    93     }
    94 
    95     static gboolean eventCallback(GSocket*, GIOCondition condition, SocketEventSource* eventSource)
    96     {
    97         ASSERT(eventSource);
    98 
    99         if (eventSource->isCancelled()) {
    100             // EventSource has been cancelled, return FALSE to destroy the source.
    101             return FALSE;
    102         }
    103 
    104         if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) {
    105             eventSource->didClose();
    106             return FALSE;
    107         }
    108 
    109         if (condition & G_IO_IN) {
    110             eventSource->performWork();
    111             return TRUE;
    112         }
    113 
    114         ASSERT_NOT_REACHED();
    115         return FALSE;
    116     }
    117 
    118 private:
    119     GCancellable* m_cancellable;
    120     std::function<void ()> m_closeFunction;
    121 };
    122 
    123 // WorkQueue
    12433static const size_t kVisualStudioThreadNameLimit = 31;
    12534
     
    17382{
    17483    GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0));
    175     ASSERT(socket);
    176     GRefPtr<GCancellable> cancellable = adoptGRef(g_cancellable_new());
    177     GRefPtr<GSource> dispatchSource = adoptGRef(g_socket_create_source(socket.get(), G_IO_IN, cancellable.get()));
    178     ASSERT(dispatchSource);
    179     SocketEventSource* eventSource = new SocketEventSource(std::move(function), this,
    180         cancellable.get(), std::move(closeFunction));
     84    ref();
     85    m_socketEventSource.schedule("[WebKit] WorkQueue::SocketEventHandler", [function, closeFunction](GIOCondition condition) {
     86            if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) {
     87                closeFunction();
     88                return GMainLoopSource::Stop;
     89            }
    18190
    182     g_source_set_callback(dispatchSource.get(), reinterpret_cast<GSourceFunc>(&WorkQueue::SocketEventSource::eventCallback),
    183         eventSource, reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource));
     91            if (condition & G_IO_IN) {
     92                function();
     93                return GMainLoopSource::Continue;
     94            }
    18495
    185     // Set up the event sources under the mutex since this is shared across multiple threads.
    186     {
    187         MutexLocker locker(m_eventSourcesLock);
    188         Vector<SocketEventSource*> sources;
    189         auto it = m_eventSources.find(fileDescriptor);
    190         if (it != m_eventSources.end())
    191             sources = it->value;
    192 
    193         sources.append(eventSource);
    194         m_eventSources.set(fileDescriptor, sources);
    195     }
    196 
    197     g_source_attach(dispatchSource.get(), m_eventContext.get());
     96            ASSERT_NOT_REACHED();
     97            return GMainLoopSource::Stop;
     98        }, socket.get(), G_IO_IN,
     99        [this] { deref(); },
     100        m_eventContext.get());
    198101}
    199102
    200 void WorkQueue::unregisterSocketEventHandler(int fileDescriptor)
     103void WorkQueue::unregisterSocketEventHandler(int)
    201104{
    202     ASSERT(fileDescriptor);
    203 
    204     MutexLocker locker(m_eventSourcesLock);
    205 
    206     ASSERT(m_eventSources.contains(fileDescriptor));
    207     auto it = m_eventSources.find(fileDescriptor);
    208 
    209     if (it != m_eventSources.end()) {
    210         Vector<SocketEventSource*> sources = it->value;
    211         for (unsigned i = 0; i < sources.size(); i++)
    212             sources[i]->cancel();
    213 
    214         m_eventSources.remove(it);
    215     }
    216 }
    217 
    218 void WorkQueue::dispatchOnSource(GSource* dispatchSource, std::function<void ()> function, GSourceFunc sourceCallback)
    219 {
    220     g_source_set_callback(dispatchSource, sourceCallback, new EventSource(std::move(function), this),
    221         reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource));
    222 
    223     g_source_attach(dispatchSource, m_eventContext.get());
     105    m_socketEventSource.cancel();
    224106}
    225107
    226108void WorkQueue::dispatch(std::function<void ()> function)
    227109{
    228     GRefPtr<GSource> dispatchSource = adoptGRef(g_idle_source_new());
    229     g_source_set_priority(dispatchSource.get(), G_PRIORITY_DEFAULT);
    230     dispatchOnSource(dispatchSource.get(), std::move(function),
    231         reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnce));
     110    ref();
     111    GMainLoopSource::createAndDeleteOnDestroy().schedule("[WebKit] WorkQueue::dispatch", std::move(function), G_PRIORITY_DEFAULT,
     112        [this] { deref(); }, m_eventContext.get());
    232113}
    233114
    234115void WorkQueue::dispatchAfter(std::chrono::nanoseconds duration, std::function<void ()> function)
    235116{
    236     GRefPtr<GSource> dispatchSource = adoptGRef(g_timeout_source_new(
    237         static_cast<guint>(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count())));
    238     dispatchOnSource(dispatchSource.get(), std::move(function),
    239         reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnce));
     117    ref();
     118    GMainLoopSource::createAndDeleteOnDestroy().scheduleAfterDelay("[WebKit] WorkQueue::dispatchAfter", std::move(function),
     119        std::chrono::duration_cast<std::chrono::milliseconds>(duration), G_PRIORITY_DEFAULT, [this] { deref(); }, m_eventContext.get());
    240120}
  • trunk/Source/WebKit2/Shared/Downloads/soup/DownloadSoup.cpp

    r169424 r169444  
    3333#include <WebCore/ResourceHandleInternal.h>
    3434#include <gio/gio.h>
     35#include <wtf/gobject/GMainLoopSource.h>
    3536#include <wtf/gobject/GRefPtr.h>
    3637#include <wtf/gobject/GUniquePtr.h>
     
    5051    DownloadClient(Download* download)
    5152        : m_download(download)
    52         , m_handleResponseLaterID(0)
    5353    {
    5454    }
     
    5656    ~DownloadClient()
    5757    {
    58         if (m_handleResponseLaterID)
    59             g_source_remove(m_handleResponseLaterID);
    6058    }
    6159
     
    118116    void didReceiveData(ResourceHandle*, const char* data, unsigned length, int /*encodedDataLength*/)
    119117    {
    120         if (m_handleResponseLaterID) {
    121             g_source_remove(m_handleResponseLaterID);
     118        if (m_handleResponseLater.isScheduled()) {
     119            m_handleResponseLater.cancel();
    122120            handleResponse();
    123121        }
     
    178176    void handleResponse()
    179177    {
    180         m_handleResponseLaterID = 0;
    181         didReceiveResponse(0, m_delayedResponse);
    182     }
    183 
    184     static gboolean handleResponseLaterCallback(DownloadClient* downloadClient)
    185     {
    186         downloadClient->handleResponse();
    187         return FALSE;
     178        didReceiveResponse(nullptr, m_delayedResponse);
    188179    }
    189180
     
    191182    {
    192183        ASSERT(m_response.isNull());
    193         ASSERT(!m_handleResponseLaterID);
     184        ASSERT(!m_handleResponseLater.isScheduled());
    194185
    195186        m_delayedResponse = response;
     
    197188        // Call didReceiveResponse in an idle to make sure the download is added
    198189        // to the DownloadManager downloads map.
    199         m_handleResponseLaterID = g_idle_add_full(G_PRIORITY_DEFAULT, reinterpret_cast<GSourceFunc>(handleResponseLaterCallback), this, 0);
     190        m_handleResponseLater.schedule("[WebKit] DownloadHandleResponseLater", std::bind(&DownloadClient::handleResponse, this));
    200191    }
    201192
     
    206197    GRefPtr<GFile> m_intermediateFile;
    207198    ResourceResponse m_delayedResponse;
    208     unsigned m_handleResponseLaterID;
     199    GMainLoopSource m_handleResponseLater;
    209200};
    210201
  • trunk/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp

    r169424 r169444  
    4646    : m_cacheFile(g_key_file_new())
    4747    , m_cachePath(g_build_filename(g_get_user_cache_dir(), "webkitgtk", "plugins", nullptr))
    48     , m_saveToFileIdleId(0)
    4948{
    5049    g_key_file_load_from_file(m_cacheFile.get(), m_cachePath.get(), G_KEY_FILE_NONE, nullptr);
     
    6463PluginInfoCache::~PluginInfoCache()
    6564{
    66     if (m_saveToFileIdleId) {
    67         g_source_remove(m_saveToFileIdleId);
     65    if (m_saveToFileIdle.isScheduled()) {
     66        m_saveToFileIdle.cancel();
    6867        saveToFile();
    6968    }
    70 }
    71 
    72 gboolean PluginInfoCache::saveToFileIdleCallback(PluginInfoCache* cache)
    73 {
    74     cache->saveToFile();
    75     return FALSE;
    7669}
    7770
     
    7972{
    8073    std::lock_guard<std::mutex> lock(m_mutex);
    81     m_saveToFileIdleId = 0;
    8274
    8375    gsize dataLength;
     
    142134    // it's done only once when this is called multiple times in a very short time.
    143135    std::lock_guard<std::mutex> lock(m_mutex);
    144     if (m_saveToFileIdleId)
     136    if (m_saveToFileIdle.isScheduled())
    145137        return;
    146138
    147     m_saveToFileIdleId = g_idle_add(reinterpret_cast<GSourceFunc>(PluginInfoCache::saveToFileIdleCallback), this);
     139    m_saveToFileIdle.schedule("[WebKit] PluginInfoCache::saveToFile", std::bind(&PluginInfoCache::saveToFile, this), G_PRIORITY_DEFAULT_IDLE);
    148140}
    149141
  • trunk/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h

    r169424 r169444  
    3232#include <mutex>
    3333#include <wtf/NeverDestroyed.h>
     34#include <wtf/gobject/GMainLoopSource.h>
    3435#include <wtf/gobject/GUniquePtr.h>
    3536
     
    5051
    5152    void saveToFile();
    52     static gboolean saveToFileIdleCallback(PluginInfoCache*);
    5353
    5454    GUniquePtr<GKeyFile> m_cacheFile;
    5555    GUniquePtr<char> m_cachePath;
    56     unsigned m_saveToFileIdleId;
     56    GMainLoopSource m_saveToFileIdle;
    5757    std::mutex m_mutex;
    5858};
  • trunk/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp

    r169424 r169444  
    7575    , m_lastFlushTime(0)
    7676    , m_layerFlushSchedulingEnabled(true)
    77     , m_layerFlushTimerCallbackId(0)
    7877{
    7978}
     
    283282}
    284283
    285 gboolean LayerTreeHostGtk::layerFlushTimerFiredCallback(LayerTreeHostGtk* layerTreeHost)
    286 {
    287     layerTreeHost->layerFlushTimerFired();
    288     return FALSE;
    289 }
    290 
    291284void LayerTreeHostGtk::layerFlushTimerFired()
    292285{
    293     ASSERT(m_layerFlushTimerCallbackId);
    294     m_layerFlushTimerCallbackId = 0;
    295 
    296286    flushAndRenderLayers();
    297287
    298     if (toTextureMapperLayer(m_rootLayer.get())->descendantsOrSelfHaveRunningAnimations() && !m_layerFlushTimerCallbackId) {
     288    if (!m_layerFlushTimerCallback.isScheduled() && toTextureMapperLayer(m_rootLayer.get())->descendantsOrSelfHaveRunningAnimations()) {
    299289        const double targetFPS = 60;
    300290        double nextFlush = std::max((1 / targetFPS) - (currentTime() - m_lastFlushTime), 0.0);
    301         m_layerFlushTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, nextFlush * 1000.0, reinterpret_cast<GSourceFunc>(layerFlushTimerFiredCallback), this, 0);
    302         g_source_set_name_by_id(m_layerFlushTimerCallbackId, "[WebKit] layerFlushTimerFiredCallback");
     291        m_layerFlushTimerCallback.scheduleAfterDelay("[WebKit] layerFlushTimer", std::bind(&LayerTreeHostGtk::layerFlushTimerFired, this),
     292            std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::duration<double>(nextFlush)), GDK_PRIORITY_EVENTS);
    303293    }
    304294}
     
    399389
    400390    // We use a GLib timer because otherwise GTK+ event handling during dragging can starve WebCore timers, which have a lower priority.
    401     if (!m_layerFlushTimerCallbackId) {
    402         m_layerFlushTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 0, reinterpret_cast<GSourceFunc>(layerFlushTimerFiredCallback), this, 0);
    403         g_source_set_name_by_id(m_layerFlushTimerCallbackId, "[WebKit] layerFlushTimerFiredCallback");
    404     }
     391    if (!m_layerFlushTimerCallback.isScheduled())
     392        m_layerFlushTimerCallback.schedule("[WebKit] layerFlushTimer", std::bind(&LayerTreeHostGtk::layerFlushTimerFired, this), GDK_PRIORITY_EVENTS);
    405393}
    406394
     
    427415void LayerTreeHostGtk::cancelPendingLayerFlush()
    428416{
    429     if (!m_layerFlushTimerCallbackId)
    430         return;
    431 
    432     g_source_remove(m_layerFlushTimerCallbackId);
    433     m_layerFlushTimerCallbackId = 0;
     417    m_layerFlushTimerCallback.cancel();
    434418}
    435419
  • trunk/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.h

    r169424 r169444  
    3737#include <wtf/HashMap.h>
    3838#include <wtf/OwnPtr.h>
     39#include <wtf/gobject/GMainLoopSource.h>
    3940
    4041namespace WebKit {
     
    9394
    9495    void layerFlushTimerFired();
    95     static gboolean layerFlushTimerFiredCallback(LayerTreeHostGtk*);
    9696
    9797    WebCore::GLContext* glContext();
     
    108108    double m_lastFlushTime;
    109109    bool m_layerFlushSchedulingEnabled;
    110     unsigned m_layerFlushTimerCallbackId;
     110    GMainLoopSource m_layerFlushTimerCallback;
    111111};
    112112
Note: See TracChangeset for help on using the changeset viewer.