Changeset 169444 in webkit
- Timestamp:
- May 29, 2014 3:33:02 AM (10 years ago)
- Location:
- trunk/Source/WebKit2
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit2/ChangeLog
r169439 r169444 1 2014-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 1 35 2014-05-28 Gavin Barraclough <baraclough@apple.com> 2 36 -
trunk/Source/WebKit2/Platform/WorkQueue.h
r169424 r169444 46 46 47 47 #if PLATFORM(GTK) 48 #include <wtf/gobject/GMainLoopSource.h> 48 49 #include <wtf/gobject/GRefPtr.h> 49 typedef gboolean (*GSourceFunc) (gpointer data);50 50 #elif PLATFORM(EFL) 51 51 #include <DispatchQueueEfl.h> … … 80 80 dispatch_queue_t m_dispatchQueue; 81 81 #elif PLATFORM(GTK) 82 class EventSource;83 class SocketEventSource;84 85 82 static void startWorkQueueThread(WorkQueue*); 86 83 void workQueueThreadBody(); 87 void dispatchOnSource(GSource*, std::function<void ()>, GSourceFunc);88 84 89 85 ThreadIdentifier m_workQueueThread; … … 91 87 Mutex m_eventLoopLock; 92 88 GRefPtr<GMainLoop> m_eventLoop; 93 Mutex m_eventSourcesLock; 94 HashMap<int, Vector<SocketEventSource*>> m_eventSources; 89 GMainLoopSource m_socketEventSource; 95 90 #elif PLATFORM(EFL) 96 91 RefPtr<DispatchQueue> m_dispatchQueue; -
trunk/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp
r169424 r169444 30 30 31 31 #include <gio/gio.h> 32 #include <glib.h>33 #include <wtf/gobject/GRefPtr.h>34 32 35 // WorkQueue::EventSource36 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() const91 {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 // WorkQueue124 33 static const size_t kVisualStudioThreadNameLimit = 31; 125 34 … … 173 82 { 174 83 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 } 181 90 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 } 184 95 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()); 198 101 } 199 102 200 void WorkQueue::unregisterSocketEventHandler(int fileDescriptor)103 void WorkQueue::unregisterSocketEventHandler(int) 201 104 { 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(); 224 106 } 225 107 226 108 void WorkQueue::dispatch(std::function<void ()> function) 227 109 { 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()); 232 113 } 233 114 234 115 void WorkQueue::dispatchAfter(std::chrono::nanoseconds duration, std::function<void ()> function) 235 116 { 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()); 240 120 } -
trunk/Source/WebKit2/Shared/Downloads/soup/DownloadSoup.cpp
r169424 r169444 33 33 #include <WebCore/ResourceHandleInternal.h> 34 34 #include <gio/gio.h> 35 #include <wtf/gobject/GMainLoopSource.h> 35 36 #include <wtf/gobject/GRefPtr.h> 36 37 #include <wtf/gobject/GUniquePtr.h> … … 50 51 DownloadClient(Download* download) 51 52 : m_download(download) 52 , m_handleResponseLaterID(0)53 53 { 54 54 } … … 56 56 ~DownloadClient() 57 57 { 58 if (m_handleResponseLaterID)59 g_source_remove(m_handleResponseLaterID);60 58 } 61 59 … … 118 116 void didReceiveData(ResourceHandle*, const char* data, unsigned length, int /*encodedDataLength*/) 119 117 { 120 if (m_handleResponseLater ID) {121 g_source_remove(m_handleResponseLaterID);118 if (m_handleResponseLater.isScheduled()) { 119 m_handleResponseLater.cancel(); 122 120 handleResponse(); 123 121 } … … 178 176 void handleResponse() 179 177 { 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); 188 179 } 189 180 … … 191 182 { 192 183 ASSERT(m_response.isNull()); 193 ASSERT(!m_handleResponseLater ID);184 ASSERT(!m_handleResponseLater.isScheduled()); 194 185 195 186 m_delayedResponse = response; … … 197 188 // Call didReceiveResponse in an idle to make sure the download is added 198 189 // to the DownloadManager downloads map. 199 m_handleResponseLater ID = g_idle_add_full(G_PRIORITY_DEFAULT, reinterpret_cast<GSourceFunc>(handleResponseLaterCallback), this, 0);190 m_handleResponseLater.schedule("[WebKit] DownloadHandleResponseLater", std::bind(&DownloadClient::handleResponse, this)); 200 191 } 201 192 … … 206 197 GRefPtr<GFile> m_intermediateFile; 207 198 ResourceResponse m_delayedResponse; 208 unsigned m_handleResponseLaterID;199 GMainLoopSource m_handleResponseLater; 209 200 }; 210 201 -
trunk/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp
r169424 r169444 46 46 : m_cacheFile(g_key_file_new()) 47 47 , m_cachePath(g_build_filename(g_get_user_cache_dir(), "webkitgtk", "plugins", nullptr)) 48 , m_saveToFileIdleId(0)49 48 { 50 49 g_key_file_load_from_file(m_cacheFile.get(), m_cachePath.get(), G_KEY_FILE_NONE, nullptr); … … 64 63 PluginInfoCache::~PluginInfoCache() 65 64 { 66 if (m_saveToFileIdle Id) {67 g_source_remove(m_saveToFileIdleId);65 if (m_saveToFileIdle.isScheduled()) { 66 m_saveToFileIdle.cancel(); 68 67 saveToFile(); 69 68 } 70 }71 72 gboolean PluginInfoCache::saveToFileIdleCallback(PluginInfoCache* cache)73 {74 cache->saveToFile();75 return FALSE;76 69 } 77 70 … … 79 72 { 80 73 std::lock_guard<std::mutex> lock(m_mutex); 81 m_saveToFileIdleId = 0;82 74 83 75 gsize dataLength; … … 142 134 // it's done only once when this is called multiple times in a very short time. 143 135 std::lock_guard<std::mutex> lock(m_mutex); 144 if (m_saveToFileIdle Id)136 if (m_saveToFileIdle.isScheduled()) 145 137 return; 146 138 147 m_saveToFileIdle Id = 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); 148 140 } 149 141 -
trunk/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h
r169424 r169444 32 32 #include <mutex> 33 33 #include <wtf/NeverDestroyed.h> 34 #include <wtf/gobject/GMainLoopSource.h> 34 35 #include <wtf/gobject/GUniquePtr.h> 35 36 … … 50 51 51 52 void saveToFile(); 52 static gboolean saveToFileIdleCallback(PluginInfoCache*);53 53 54 54 GUniquePtr<GKeyFile> m_cacheFile; 55 55 GUniquePtr<char> m_cachePath; 56 unsigned m_saveToFileIdleId;56 GMainLoopSource m_saveToFileIdle; 57 57 std::mutex m_mutex; 58 58 }; -
trunk/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp
r169424 r169444 75 75 , m_lastFlushTime(0) 76 76 , m_layerFlushSchedulingEnabled(true) 77 , m_layerFlushTimerCallbackId(0)78 77 { 79 78 } … … 283 282 } 284 283 285 gboolean LayerTreeHostGtk::layerFlushTimerFiredCallback(LayerTreeHostGtk* layerTreeHost)286 {287 layerTreeHost->layerFlushTimerFired();288 return FALSE;289 }290 291 284 void LayerTreeHostGtk::layerFlushTimerFired() 292 285 { 293 ASSERT(m_layerFlushTimerCallbackId);294 m_layerFlushTimerCallbackId = 0;295 296 286 flushAndRenderLayers(); 297 287 298 if ( toTextureMapperLayer(m_rootLayer.get())->descendantsOrSelfHaveRunningAnimations() && !m_layerFlushTimerCallbackId) {288 if (!m_layerFlushTimerCallback.isScheduled() && toTextureMapperLayer(m_rootLayer.get())->descendantsOrSelfHaveRunningAnimations()) { 299 289 const double targetFPS = 60; 300 290 double nextFlush = std::max((1 / targetFPS) - (currentTime() - m_lastFlushTime), 0.0); 301 m_layerFlushTimerCallback Id = 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); 303 293 } 304 294 } … … 399 389 400 390 // 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); 405 393 } 406 394 … … 427 415 void LayerTreeHostGtk::cancelPendingLayerFlush() 428 416 { 429 if (!m_layerFlushTimerCallbackId) 430 return; 431 432 g_source_remove(m_layerFlushTimerCallbackId); 433 m_layerFlushTimerCallbackId = 0; 417 m_layerFlushTimerCallback.cancel(); 434 418 } 435 419 -
trunk/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.h
r169424 r169444 37 37 #include <wtf/HashMap.h> 38 38 #include <wtf/OwnPtr.h> 39 #include <wtf/gobject/GMainLoopSource.h> 39 40 40 41 namespace WebKit { … … 93 94 94 95 void layerFlushTimerFired(); 95 static gboolean layerFlushTimerFiredCallback(LayerTreeHostGtk*);96 96 97 97 WebCore::GLContext* glContext(); … … 108 108 double m_lastFlushTime; 109 109 bool m_layerFlushSchedulingEnabled; 110 unsigned m_layerFlushTimerCallbackId;110 GMainLoopSource m_layerFlushTimerCallback; 111 111 }; 112 112
Note: See TracChangeset
for help on using the changeset viewer.