WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
WIP
bug-138691-20150610021845.patch (text/plain), 31.44 KB, created by
Zan Dobersek
on 2015-06-10 02:19:13 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Zan Dobersek
Created:
2015-06-10 02:19:13 PDT
Size:
31.44 KB
patch
obsolete
>Subversion Revision: 185402 >diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog >index b0c7f97cc7c416d3d085daa3a8dc1b20cc57d960..26567cdaf7318dc88ac5c190f09a1d48f8f0e792 100644 >--- a/Source/WTF/ChangeLog >+++ b/Source/WTF/ChangeLog >@@ -1,3 +1,60 @@ >+2015-06-10 Zan Dobersek <zdobersek@igalia.com> >+ >+ [GTK] Add persistent GSource wrapper >+ https://bugs.webkit.org/show_bug.cgi?id=138691 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * wtf/PlatformGTK.cmake: >+ * wtf/RunLoop.h: >+ * wtf/WorkQueue.h: >+ * wtf/glib/MainThreadGLib.cpp: >+ (WTF::scheduleDispatchFunctionsOnMainThread): >+ * wtf/glib/RunLoopGLib.cpp: >+ (WTF::RunLoop::RunLoop): >+ (WTF::RunLoop::wakeUp): >+ (WTF::RunLoop::TimerBase::TimerBase): >+ (WTF::RunLoop::TimerBase::start): >+ (WTF::RunLoop::TimerBase::stop): >+ (WTF::RunLoop::TimerBase::timerFired): >+ * wtf/glib/WorkQueueGLib.cpp: >+ (WTF::WorkQueue::platformInitialize): >+ (WTF::WorkQueue::platformInvalidate): >+ (WTF::WorkQueue::registerSocketEventHandler): >+ (WTF::WorkQueue::dispatch): >+ (WTF::WorkQueue::dispatchAfter): >+ * wtf/gobject/GSourceWrap.cpp: Added. >+ (WTF::GSourceWrap::staticDelayBasedVoidCallback): >+ (WTF::GSourceWrap::dynamicDelayBasedVoidCallback): >+ (WTF::GSourceWrap::dynamicDelayBasedBoolCallback): >+ (WTF::GSourceWrap::staticOneShotCallback): >+ (WTF::GSourceWrap::staticSocketCallback): >+ (WTF::GSourceWrap::targetTimeForDelay): >+ (WTF::GSourceWrap::Base::~Base): >+ (WTF::GSourceWrap::DelayBased::isScheduled): >+ (WTF::GSourceWrap::DelayBased::isActive): >+ (WTF::GSourceWrap::DelayBased::initialize): >+ (WTF::GSourceWrap::DelayBased::schedule): >+ (WTF::GSourceWrap::DelayBased::cancel): >+ (WTF::GSourceWrap::Static::Static): >+ (WTF::GSourceWrap::Static::initialize): >+ (WTF::GSourceWrap::Static::schedule): >+ (WTF::GSourceWrap::Static::cancel): >+ (WTF::GSourceWrap::Dynamic::Dynamic): >+ (WTF::GSourceWrap::Dynamic::schedule): >+ (WTF::GSourceWrap::Dynamic::cancel): >+ (WTF::GSourceWrap::OneShot::construct): >+ (WTF::GSourceWrap::Socket::initialize): >+ (WTF::GSourceWrap::Socket::cancel): >+ (WTF::GSourceWrap::Queue::Queue): >+ (WTF::GSourceWrap::Queue::~Queue): >+ (WTF::GSourceWrap::Queue::initialize): >+ (WTF::GSourceWrap::Queue::queue): >+ (WTF::GSourceWrap::Queue::dispatchQueue): >+ * wtf/gobject/GSourceWrap.h: Added. >+ (WTF::GSourceWrap::destroyCallbackContext): >+ (WTF::GSourceWrap::Base::isInitialized): >+ > 2015-06-09 Csaba Osztrogonác <ossy@webkit.org> > > [cmake] Fix the style issues in cmake project files >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 1f8abbeec9a9cce5e0615d80e0c0fb7ce011a32c..c7832f6290530eb690199e1f07cbcac441005f9d 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,19 @@ >+2015-06-10 Zan Dobersek <zdobersek@igalia.com> >+ >+ [GTK] Add persistent GSource wrapper >+ https://bugs.webkit.org/show_bug.cgi?id=138691 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ No new tests (OOPS!). >+ >+ * platform/gtk/SharedTimerGtk.cpp: >+ (WebCore::sharedTimerFire): >+ (WebCore::setSharedTimerFireInterval): >+ * platform/network/ResourceHandleInternal.h: >+ * platform/network/soup/ResourceHandleSoup.cpp: >+ (WebCore::ResourceHandle::sendPendingRequest): >+ > 2015-06-09 Daegyu Lee <daegyu.lee@navercorp.com> > > 3D-transformed video does not display on platforms without accelerated video rendering >diff --git a/Source/WTF/wtf/PlatformGTK.cmake b/Source/WTF/wtf/PlatformGTK.cmake >index 58e3cd871e22b91e3d9fce982e322019706bed83..efb7bc904a9f2255e132c088221c9ce97f07943b 100644 >--- a/Source/WTF/wtf/PlatformGTK.cmake >+++ b/Source/WTF/wtf/PlatformGTK.cmake >@@ -8,6 +8,7 @@ list(APPEND WTF_SOURCES > > gobject/GMainLoopSource.cpp > gobject/GRefPtr.cpp >+ gobject/GSourceWrap.cpp > gobject/GThreadSafeMainLoopSource.cpp > gobject/GlibUtilities.cpp > ) >diff --git a/Source/WTF/wtf/RunLoop.h b/Source/WTF/wtf/RunLoop.h >index 850bce970de94ea723a1b46673382fd4f8d69ae0..2382b56d29b2dbeca6a75277110df8784ed63442 100644 >--- a/Source/WTF/wtf/RunLoop.h >+++ b/Source/WTF/wtf/RunLoop.h >@@ -36,7 +36,7 @@ > #include <wtf/Threading.h> > > #if USE(GLIB) >-#include <wtf/gobject/GMainLoopSource.h> >+#include <wtf/gobject/GSourceWrap.h> > #endif > > #if PLATFORM(EFL) >@@ -100,7 +100,10 @@ public: > Ecore_Timer* m_timer; > bool m_isRepeating; > #elif USE(GLIB) >- GMainLoopSource m_timerSource; >+ void timerFired(); >+ double m_fireInterval { 0 }; >+ bool m_repeating { false }; >+ GSourceWrap::Static m_timerSource; > #endif > }; > >@@ -160,6 +163,7 @@ public: > private: > GRefPtr<GMainContext> m_mainContext; > Vector<GRefPtr<GMainLoop>> m_mainLoops; >+ GSourceWrap::Static m_workSource; > #endif > }; > >diff --git a/Source/WTF/wtf/WorkQueue.h b/Source/WTF/wtf/WorkQueue.h >index 15d755f2858572974e6741fc720d65a7a850f2f1..f1529d9256d5ae4b8f1883cce3c4987918a306d3 100644 >--- a/Source/WTF/wtf/WorkQueue.h >+++ b/Source/WTF/wtf/WorkQueue.h >@@ -39,8 +39,8 @@ > #endif > > #if PLATFORM(GTK) >-#include <wtf/gobject/GMainLoopSource.h> > #include <wtf/gobject/GRefPtr.h> >+#include <wtf/gobject/GSourceWrap.h> > #elif PLATFORM(EFL) > #include <DispatchQueueEfl.h> > #elif OS(WINDOWS) >@@ -107,7 +107,8 @@ private: > ThreadIdentifier m_workQueueThread; > GRefPtr<GMainContext> m_eventContext; > GRefPtr<GMainLoop> m_eventLoop; >- GMainLoopSource m_socketEventSource; >+ GSourceWrap::Socket m_socketEventSource; >+ GSourceWrap::Queue m_dispatchQueue; > #elif PLATFORM(EFL) > RefPtr<DispatchQueue> m_dispatchQueue; > #elif OS(WINDOWS) >diff --git a/Source/WTF/wtf/glib/MainThreadGLib.cpp b/Source/WTF/wtf/glib/MainThreadGLib.cpp >index 598129af8dc2247de62b224563a02d5282335e79..d772f223965d21410dcfd2b732c3a38399000265 100644 >--- a/Source/WTF/wtf/glib/MainThreadGLib.cpp >+++ b/Source/WTF/wtf/glib/MainThreadGLib.cpp >@@ -30,7 +30,7 @@ > #include "config.h" > #include "MainThread.h" > >-#include <wtf/gobject/GMainLoopSource.h> >+#include <wtf/gobject/GSourceWrap.h> > > namespace WTF { > >@@ -40,7 +40,9 @@ void initializeMainThreadPlatform() > > void scheduleDispatchFunctionsOnMainThread() > { >- GMainLoopSource::scheduleAndDeleteOnDestroy("[WebKit] dispatchFunctionsFromMainThread", std::function<void()>(dispatchFunctionsFromMainThread)); >+ static GSourceWrap::Static dispatcher("[WebKit] dispatchFunctionsFromMainThread", >+ std::function<void ()>(dispatchFunctionsFromMainThread), G_PRIORITY_DEFAULT, g_main_context_default()); >+ dispatcher.schedule(); > } > > } // namespace WTF >diff --git a/Source/WTF/wtf/glib/RunLoopGLib.cpp b/Source/WTF/wtf/glib/RunLoopGLib.cpp >index 7dc407566082a238baf96108762eec242f6eb98b..032b3346ef9bfb84c3107b9d563c53dea7ab61d4 100644 >--- a/Source/WTF/wtf/glib/RunLoopGLib.cpp >+++ b/Source/WTF/wtf/glib/RunLoopGLib.cpp >@@ -42,6 +42,9 @@ RunLoop::RunLoop() > GRefPtr<GMainLoop> innermostLoop = adoptGRef(g_main_loop_new(m_mainContext.get(), FALSE)); > ASSERT(innermostLoop); > m_mainLoops.append(innermostLoop); >+ >+ m_workSource.initialize("[WebKit] RunLoop work", std::bind(&RunLoop::performWork, this), >+ G_PRIORITY_DEFAULT, m_mainContext.get()); > } > > RunLoop::~RunLoop() >@@ -91,15 +94,13 @@ 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()); >+ m_workSource.schedule(); > g_main_context_wakeup(m_mainContext.get()); > } > > RunLoop::TimerBase::TimerBase(RunLoop& runLoop) > : m_runLoop(runLoop) >+ , m_timerSource("[WebKit] RunLoop::Timer", std::bind(&RunLoop::TimerBase::timerFired, this), G_PRIORITY_DEFAULT, m_runLoop.m_mainContext.get()) > { > } > >@@ -110,12 +111,15 @@ RunLoop::TimerBase::~TimerBase() > > 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 = fireInterval; >+ m_repeating = repeat; >+ m_timerSource.schedule(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(m_fireInterval))); > } > > void RunLoop::TimerBase::stop() > { >+ m_fireInterval = 0; >+ m_repeating = false; > m_timerSource.cancel(); > } > >@@ -124,4 +128,11 @@ bool RunLoop::TimerBase::isActive() const > return m_timerSource.isScheduled(); > } > >+void RunLoop::TimerBase::timerFired() >+{ >+ fired(); >+ if (m_repeating) >+ m_timerSource.schedule(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(m_fireInterval))); >+} >+ > } // namespace WTF >diff --git a/Source/WTF/wtf/glib/WorkQueueGLib.cpp b/Source/WTF/wtf/glib/WorkQueueGLib.cpp >index ee1b60baf5d068ba2cead3d81148fb4a2c7c41b2..8341808a83d67361225a307a42aa3c9786ba80d9 100644 >--- a/Source/WTF/wtf/glib/WorkQueueGLib.cpp >+++ b/Source/WTF/wtf/glib/WorkQueueGLib.cpp >@@ -42,6 +42,8 @@ void WorkQueue::platformInitialize(const char* name, Type, QOS) > m_eventLoop = adoptGRef(g_main_loop_new(m_eventContext.get(), FALSE)); > ASSERT(m_eventLoop); > >+ m_dispatchQueue.initialize("[WebKit] WorkQueue::dispatch", G_PRIORITY_DEFAULT, m_eventContext.get()); >+ > // This name can be com.apple.WebKit.ProcessLauncher or com.apple.CoreIPC.ReceiveQueue. > // We are using those names for the thread name, but both are longer than 31 characters, > // which is the limit of Visual Studio for thread names. >@@ -75,8 +77,9 @@ void WorkQueue::platformInvalidate() > 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("[WebKit] WorkQueue quit main loop", [eventLoop] { g_main_loop_quit(eventLoop); }, >- G_PRIORITY_HIGH, nullptr, m_eventContext.get()); >+ GSourceWrap::OneShot::construct("[WebKit] WorkQueue quit main loop", >+ [eventLoop] { g_main_loop_quit(eventLoop); }, std::chrono::microseconds(0), >+ G_PRIORITY_HIGH, m_eventContext.get()); > } > m_eventLoop = nullptr; > } >@@ -87,23 +90,22 @@ void WorkQueue::platformInvalidate() > void WorkQueue::registerSocketEventHandler(int fileDescriptor, std::function<void ()> function, std::function<void ()> closeFunction) > { > GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0)); >- ref(); >- m_socketEventSource.schedule("[WebKit] WorkQueue::SocketEventHandler", [function, closeFunction](GIOCondition condition) { >+ RefPtr<WorkQueue> protector(this); >+ m_socketEventSource.initialize("[WebKit] WorkQueue::SocketEventHandler", >+ [function, closeFunction, protector](GIOCondition condition) { > if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) { > closeFunction(); >- return GMainLoopSource::Stop; >+ return false; > } > > if (condition & G_IO_IN) { > function(); >- return GMainLoopSource::Continue; >+ return true; > } > > ASSERT_NOT_REACHED(); >- return GMainLoopSource::Stop; >- }, socket.get(), G_IO_IN, >- [this] { deref(); }, >- m_eventContext.get()); >+ return false; >+ }, socket.get(), G_IO_IN, G_PRIORITY_DEFAULT, m_eventContext.get()); > } > > void WorkQueue::unregisterSocketEventHandler(int) >@@ -113,16 +115,14 @@ void WorkQueue::unregisterSocketEventHandler(int) > > void WorkQueue::dispatch(std::function<void ()> function) > { >- ref(); >- GMainLoopSource::scheduleAndDeleteOnDestroy("[WebKit] WorkQueue::dispatch", WTF::move(function), G_PRIORITY_DEFAULT, >- [this] { deref(); }, m_eventContext.get()); >+ m_dispatchQueue.queue(WTF::move(function)); > } > > void WorkQueue::dispatchAfter(std::chrono::nanoseconds duration, std::function<void ()> function) > { >- ref(); >- GMainLoopSource::scheduleAfterDelayAndDeleteOnDestroy("[WebKit] WorkQueue::dispatchAfter", WTF::move(function), >- std::chrono::duration_cast<std::chrono::milliseconds>(duration), G_PRIORITY_DEFAULT, [this] { deref(); }, m_eventContext.get()); >+ RefPtr<WorkQueue> protector(this); >+ GSourceWrap::OneShot::construct("[WebKit] WorkQueue::dispatchAfter", std::bind([protector](const std::function<void ()>& function) { function(); }, WTF::move(function)), >+ std::chrono::duration_cast<std::chrono::milliseconds>(duration), G_PRIORITY_DEFAULT, m_eventContext.get()); > } > > } >diff --git a/Source/WTF/wtf/gobject/GSourceWrap.cpp b/Source/WTF/wtf/gobject/GSourceWrap.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..1a54d3bf57f99dc3cf2cb7a4ddf274ea94cda6fa >--- /dev/null >+++ b/Source/WTF/wtf/gobject/GSourceWrap.cpp >@@ -0,0 +1,302 @@ >+#include "config.h" >+#include "GSourceWrap.h" >+ >+#include <gio/gio.h> >+#include <wtf/gobject/GMutexLocker.h> >+#include <cstdio> >+ >+namespace WTF { >+ >+GSourceFuncs GSourceWrap::sourceFunctions = { >+ // prepare >+ [](GSource* source, gint*) -> gboolean >+ { >+ return g_source_get_ready_time(source) == 0; >+ }, >+ nullptr, // check >+ // dispatch >+ [](GSource* source, GSourceFunc callback, gpointer data) -> gboolean >+ { >+ ASSERT(source); >+ if (g_source_get_ready_time(source) == -1) >+ return G_SOURCE_CONTINUE; >+ DispatchContext context{ source, data }; >+ return callback(&context); >+ }, >+ nullptr, // finalize >+ nullptr, // closure_callback >+ nullptr, // closure_marshall >+}; >+ >+gboolean GSourceWrap::staticDelayBasedVoidCallback(gpointer data) >+{ >+ auto& dispatch = *reinterpret_cast<DispatchContext*>(data); >+ auto& callback = *reinterpret_cast<DelayBased::CallbackContext<void ()>*>(dispatch.second); >+ if (g_cancellable_is_cancelled(callback.second.cancellable.get())) >+ return G_SOURCE_CONTINUE; >+ >+ callback.second.dispatching = true; >+ g_source_set_ready_time(dispatch.first, -1); >+ >+ callback.first(); >+ >+ callback.second.dispatching = false; >+ return G_SOURCE_CONTINUE; >+} >+ >+gboolean GSourceWrap::dynamicDelayBasedVoidCallback(gpointer data) >+{ >+ auto& dispatch = *reinterpret_cast<DispatchContext*>(data); >+ auto& callback = *reinterpret_cast<DelayBased::CallbackContext<void ()>*>(dispatch.second); >+ if (g_cancellable_is_cancelled(callback.second.cancellable.get())) >+ return G_SOURCE_CONTINUE; >+ >+ callback.second.dispatching = true; >+ g_source_set_ready_time(dispatch.first, -1); >+ g_source_set_callback(dispatch.first, nullptr, nullptr, nullptr); >+ >+ callback.first(); >+ >+ callback.second.dispatching = false; >+ return G_SOURCE_CONTINUE; >+} >+ >+gboolean GSourceWrap::dynamicDelayBasedBoolCallback(gpointer data) >+{ >+ auto& dispatch = *reinterpret_cast<DispatchContext*>(data); >+ auto& callback = *reinterpret_cast<DelayBased::CallbackContext<bool ()>*>(dispatch.second); >+ if (g_cancellable_is_cancelled(callback.second.cancellable.get())) >+ return G_SOURCE_CONTINUE; >+ >+ callback.second.dispatching = true; >+ g_source_set_ready_time(dispatch.first, -1); >+ >+ if (callback.first()) >+ g_source_set_ready_time(dispatch.first, targetTimeForDelay(callback.second.delay)); >+ else >+ g_source_set_callback(dispatch.first, nullptr, nullptr, nullptr); >+ >+ callback.second.dispatching = false; >+ return G_SOURCE_CONTINUE; >+} >+ >+gboolean GSourceWrap::staticOneShotCallback(gpointer data) >+{ >+ auto& dispatch = *reinterpret_cast<DispatchContext*>(data); >+ auto& callback = *reinterpret_cast<OneShot::CallbackContext*>(dispatch.second); >+ >+ g_source_set_ready_time(dispatch.first, -1); >+ callback.first(); >+ >+ return G_SOURCE_REMOVE; >+} >+ >+gboolean GSourceWrap::staticSocketCallback(GSocket*, GIOCondition condition, gpointer data) >+{ >+ auto& callback = *reinterpret_cast<Socket::CallbackContext*>(data); >+ if (g_cancellable_is_cancelled(callback.second.get())) >+ return G_SOURCE_REMOVE; >+ >+ return callback.first(condition); >+} >+ >+gint64 GSourceWrap::targetTimeForDelay(std::chrono::microseconds delay) >+{ >+ if (!delay.count()) >+ return 0; >+ >+ gint64 currentTime = g_get_monotonic_time(); >+ gint64 targetTime = currentTime + std::min<gint64>(G_MAXINT64 - currentTime, delay.count()); >+ ASSERT(targetTime >= currentTime); >+ >+ return targetTime; >+} >+ >+GSourceWrap::Base::~Base() >+{ >+ if (m_source) >+ g_source_destroy(m_source.get()); >+} >+ >+bool GSourceWrap::DelayBased::isScheduled() const >+{ >+ ASSERT(m_source); >+ return g_source_get_ready_time(m_source.get()) != -1; >+} >+ >+bool GSourceWrap::DelayBased::isActive() const >+{ >+ return isScheduled() || m_context.dispatching; >+} >+ >+void GSourceWrap::DelayBased::initialize(const char* name, int priority, GMainContext* context) >+{ >+ ASSERT(!m_source); >+ m_source = adoptGRef(g_source_new(&sourceFunctions, sizeof(GSource))); >+ >+ m_context.delay = std::chrono::microseconds(0); >+ m_context.cancellable = adoptGRef(g_cancellable_new()); >+ m_context.dispatching = false; >+ >+ g_source_set_name(m_source.get(), name); >+ g_source_set_priority(m_source.get(), priority); >+ >+ if (!context) >+ context = g_main_context_get_thread_default(); >+ g_source_attach(m_source.get(), context); >+} >+ >+void GSourceWrap::DelayBased::schedule(std::chrono::microseconds delay) >+{ >+ ASSERT(m_source); >+ m_context.delay = delay; >+ >+ if (g_cancellable_is_cancelled(m_context.cancellable.get())) >+ m_context.cancellable = adoptGRef(g_cancellable_new()); >+ >+ g_source_set_ready_time(m_source.get(), targetTimeForDelay(delay)); >+} >+ >+void GSourceWrap::DelayBased::cancel() >+{ >+ ASSERT(m_source); >+ g_cancellable_cancel(m_context.cancellable.get()); >+ g_source_set_ready_time(m_source.get(), -1); >+} >+ >+GSourceWrap::Static::Static(const char* name, std::function<void ()>&& function, int priority, GMainContext* context) >+{ >+ initialize(name, WTF::move(function), priority, context); >+} >+ >+void GSourceWrap::Static::initialize(const char* name, std::function<void ()>&& function, int priority, GMainContext* context) >+{ >+ DelayBased::initialize(name, priority, context); >+ >+ g_source_set_callback(m_source.get(), static_cast<GSourceFunc>(staticDelayBasedVoidCallback), >+ new CallbackContext<void ()>{ WTF::move(function), m_context }, static_cast<GDestroyNotify>(destroyCallbackContext<CallbackContext<void ()>>)); >+} >+ >+void GSourceWrap::Static::schedule(std::chrono::microseconds delay) >+{ >+ DelayBased::schedule(delay); >+} >+ >+void GSourceWrap::Static::cancel() >+{ >+ if (!m_source) >+ return; >+ >+ DelayBased::cancel(); >+} >+ >+GSourceWrap::Dynamic::Dynamic(const char* name, int priority, GMainContext* context) >+{ >+ DelayBased::initialize(name, priority, context); >+} >+ >+void GSourceWrap::Dynamic::schedule(std::function<void ()>&& function, std::chrono::microseconds delay) >+{ >+ g_source_set_callback(m_source.get(), static_cast<GSourceFunc>(dynamicDelayBasedVoidCallback), >+ new CallbackContext<void ()>{ WTF::move(function), m_context }, static_cast<GDestroyNotify>(destroyCallbackContext<CallbackContext<void ()>>)); >+ >+ DelayBased::schedule(delay); >+} >+ >+void GSourceWrap::Dynamic::schedule(std::function<bool ()>&& function, std::chrono::microseconds delay) >+{ >+ g_source_set_callback(m_source.get(), static_cast<GSourceFunc>(dynamicDelayBasedBoolCallback), >+ new CallbackContext<bool ()>{ WTF::move(function), m_context }, static_cast<GDestroyNotify>(destroyCallbackContext<CallbackContext<bool ()>>)); >+ >+ DelayBased::schedule(delay); >+} >+ >+void GSourceWrap::Dynamic::cancel() >+{ >+ if (!m_source) >+ return; >+ >+ DelayBased::cancel(); >+ g_source_set_callback(m_source.get(), nullptr, nullptr, nullptr); >+} >+ >+void GSourceWrap::OneShot::construct(const char* name, std::function<void ()>&& function, std::chrono::microseconds delay, int priority, GMainContext* context) >+{ >+ GRefPtr<GSource> source = adoptGRef(g_source_new(&sourceFunctions, sizeof(GSource))); >+ >+ g_source_set_name(source.get(), name); >+ g_source_set_priority(source.get(), priority); >+ >+ g_source_set_callback(source.get(), static_cast<GSourceFunc>(staticOneShotCallback), >+ new CallbackContext{ WTF::move(function), nullptr }, static_cast<GDestroyNotify>(destroyCallbackContext<CallbackContext>)); >+ g_source_set_ready_time(source.get(), targetTimeForDelay(delay)); >+ >+ if (!context) >+ context = g_main_context_get_thread_default(); >+ g_source_attach(source.get(), context); >+} >+ >+void GSourceWrap::Socket::initialize(const char* name, std::function<bool (GIOCondition)>&& function, GSocket* socket, GIOCondition condition, int priority, GMainContext* context) >+{ >+ ASSERT(!m_source); >+ GCancellable* cancellable = g_cancellable_new(); >+ m_source = adoptGRef(g_socket_create_source(socket, condition, cancellable)); >+ m_cancellable = adoptGRef(cancellable); >+ >+ g_source_set_name(m_source.get(), name); >+ g_source_set_priority(m_source.get(), priority); >+ >+ g_source_set_callback(m_source.get(), reinterpret_cast<GSourceFunc>(staticSocketCallback), >+ new CallbackContext{ WTF::move(function), m_cancellable }, static_cast<GDestroyNotify>(destroyCallbackContext<CallbackContext>)); >+ >+ if (!context) >+ context = g_main_context_get_thread_default(); >+ g_source_attach(m_source.get(), context); >+} >+ >+void GSourceWrap::Socket::cancel() >+{ >+ g_cancellable_cancel(m_cancellable.get()); >+} >+ >+GSourceWrap::Queue::Queue() >+{ >+ g_mutex_init(&m_mutex); >+} >+ >+GSourceWrap::Queue::~Queue() >+{ >+ g_mutex_clear(&m_mutex); >+} >+ >+void GSourceWrap::Queue::initialize(const char* name, int priority, GMainContext* context) >+{ >+ m_sourceWrap.initialize(name, std::bind(&Queue::dispatchQueue, this), priority, context); >+} >+ >+void GSourceWrap::Queue::queue(std::function<void ()>&& function) >+{ >+ WTF::GMutexLocker<GMutex> lock(m_mutex); >+ m_queue.append(WTF::move(function)); >+ >+ m_sourceWrap.schedule(); >+} >+ >+void GSourceWrap::Queue::dispatchQueue() >+{ >+ while (1) { >+ decltype(m_queue) queue; >+ { >+ WTF::GMutexLocker<GMutex> lock(m_mutex); >+ queue = WTF::move(m_queue); >+ } >+ >+ if (!queue.size()) >+ break; >+ >+ for (auto& function : queue) >+ function(); >+ } >+} >+ >+} // namespace WTF >diff --git a/Source/WTF/wtf/gobject/GSourceWrap.h b/Source/WTF/wtf/gobject/GSourceWrap.h >new file mode 100644 >index 0000000000000000000000000000000000000000..af14d54ab35f3b6e48f97331596577b82c5869b3 >--- /dev/null >+++ b/Source/WTF/wtf/gobject/GSourceWrap.h >@@ -0,0 +1,144 @@ >+#ifndef GSourceWrap_h >+#define GSourceWrap_h >+ >+#include <chrono> >+#include <functional> >+#include <glib.h> >+#include <utility> >+#include <wtf/Vector.h> >+#include <wtf/gobject/GRefPtr.h> >+ >+typedef struct _GSocket GSocket; >+ >+namespace WTF { >+ >+class GSourceWrap { >+private: >+ static GSourceFuncs sourceFunctions; >+ static gboolean staticDelayBasedVoidCallback(gpointer); >+ static gboolean dynamicDelayBasedVoidCallback(gpointer); >+ static gboolean dynamicDelayBasedBoolCallback(gpointer); >+ static gboolean staticOneShotCallback(gpointer); >+ static gboolean staticSocketCallback(GSocket*, GIOCondition, gpointer); >+ >+ using DispatchContext = std::pair<GSource*, gpointer>; >+ template<typename T1, typename T2> >+ using CallbackContextType = std::pair<std::function<T1>, T2>; >+ >+ template<typename T> >+ static void destroyCallbackContext(gpointer data) >+ { >+ auto* context = reinterpret_cast<T*>(data); >+ delete context; >+ } >+ >+ static gint64 targetTimeForDelay(std::chrono::microseconds); >+ >+ class Base { >+ Base(const Base&) = delete; >+ Base& operator=(const Base&) = delete; >+ Base(Base&&) = delete; >+ Base& operator=(Base&&) = delete; >+ public: >+ Base() = default; >+ ~Base(); >+ >+ protected: >+ bool isInitialized() const { return !!m_source; } >+ >+ GRefPtr<GSource> m_source; >+ }; >+ >+ class DelayBased : Base { >+ public: >+ DelayBased() = default; >+ >+ using Base::isInitialized; >+ bool isScheduled() const; >+ bool isActive() const; >+ >+ protected: >+ void initialize(const char* name, int priority, GMainContext*); >+ void schedule(std::chrono::microseconds); >+ void cancel(); >+ >+ struct Context { >+ std::chrono::microseconds delay; >+ GRefPtr<GCancellable> cancellable; >+ bool dispatching; >+ } m_context; >+ >+ friend class GSourceWrap; >+ template<typename T> >+ using CallbackContext = CallbackContextType<T, Context&>; >+ }; >+ >+public: >+ class Static : public DelayBased { >+ public: >+ Static() = default; >+ Static(const char* name, std::function<void ()>&&, int priority = G_PRIORITY_DEFAULT, GMainContext* = nullptr); >+ void initialize(const char* name, std::function<void ()>&&, int priority = G_PRIORITY_DEFAULT, GMainContext* = nullptr); >+ >+ void schedule(std::chrono::microseconds = std::chrono::microseconds(0)); >+ void cancel(); >+ }; >+ >+ class Dynamic : public DelayBased { >+ public: >+ Dynamic(const char* name, int priority = G_PRIORITY_DEFAULT, GMainContext* = nullptr); >+ >+ void schedule(std::function<void ()>&&, std::chrono::microseconds = std::chrono::microseconds(0)); >+ void schedule(std::function<bool ()>&&, std::chrono::microseconds = std::chrono::microseconds(0)); >+ void cancel(); >+ }; >+ >+ class OneShot { >+ public: >+ static void construct(const char* name, std::function<void ()>&& function, std::chrono::microseconds delay = std::chrono::microseconds(0), int priority = G_PRIORITY_DEFAULT, GMainContext* context = nullptr); >+ >+ private: >+ friend class GSourceWrap; >+ using CallbackContext = CallbackContextType<void (), void*>; >+ }; >+ >+ class Socket : public Base { >+ public: >+ Socket() = default; >+ void initialize(const char* name, std::function<bool (GIOCondition)>&&, GSocket*, GIOCondition, int priority = G_PRIORITY_DEFAULT, GMainContext* = nullptr); >+ void cancel(); >+ >+ private: >+ friend class GSourceWrap; >+ using CallbackContext = CallbackContextType<bool (GIOCondition), GRefPtr<GCancellable>>; >+ >+ GRefPtr<GCancellable> m_cancellable; >+ }; >+ >+ class Queue { >+ Queue(const Queue&) = delete; >+ Queue& operator=(const Queue&) = delete; >+ Queue(Queue&&) = delete; >+ Queue& operator=(Queue&&) = delete; >+ public: >+ Queue(); >+ ~Queue(); >+ >+ void initialize(const char*, int priority = G_PRIORITY_DEFAULT, GMainContext* = nullptr); >+ >+ void queue(std::function<void ()>&&); >+ >+ private: >+ void dispatchQueue(); >+ >+ Static m_sourceWrap; >+ GMutex m_mutex; >+ Vector<std::function<void ()>, 16> m_queue; >+ }; >+}; >+ >+} // namespace WTF >+ >+using WTF::GSourceWrap; >+ >+#endif // GSourceWrap_h >diff --git a/Source/WebCore/platform/gtk/SharedTimerGtk.cpp b/Source/WebCore/platform/gtk/SharedTimerGtk.cpp >index 133e906fa0f05809b6a50a00e9918bdc1d680398..d53faf028333a7bdbb4eb089be949340ea183928 100644 >--- a/Source/WebCore/platform/gtk/SharedTimerGtk.cpp >+++ b/Source/WebCore/platform/gtk/SharedTimerGtk.cpp >@@ -28,12 +28,18 @@ > #include "config.h" > #include "SharedTimer.h" > >-#include <wtf/gobject/GMainLoopSource.h> >+#include <wtf/gobject/GSourceWrap.h> > > namespace WebCore { > >-static GMainLoopSource gSharedTimer; >-static void (*sharedTimerFiredFunction)(); >+static void (*sharedTimerFiredFunction)() = nullptr; >+static void sharedTimerFire() >+{ >+ sharedTimerFiredFunction(); >+} >+ >+// G_PRIORITY_HIGH_IDLE + 20 is GDK_PRIORITY_REDRAW, but we don't want to depend on GDK here just to use a constant. >+static GSourceWrap::Static gSharedTimer("[WebKit] sharedTimerTimeoutCallback", std::function<void ()>(sharedTimerFire), G_PRIORITY_HIGH_IDLE + 20); > > void setSharedTimerFiredFunction(void (*f)()) > { >@@ -46,10 +52,11 @@ void setSharedTimerFireInterval(double interval) > { > ASSERT(sharedTimerFiredFunction); > >- // This is GDK_PRIORITY_REDRAW, but we don't want to depend on GDK here just to use a constant. >- static const int priority = G_PRIORITY_HIGH_IDLE + 20; >- gSharedTimer.scheduleAfterDelay("[WebKit] sharedTimerTimeoutCallback", std::function<void()>(sharedTimerFiredFunction), >- std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(interval)), priority); >+ auto intervalDuration = std::chrono::duration<double>(interval); >+ auto delay = std::chrono::microseconds::max(); >+ if (intervalDuration < delay) >+ delay = std::chrono::duration_cast<std::chrono::microseconds>(intervalDuration); >+ gSharedTimer.schedule(delay); > } > > void stopSharedTimer() >diff --git a/Source/WebCore/platform/network/ResourceHandleInternal.h b/Source/WebCore/platform/network/ResourceHandleInternal.h >index 6bcd5362169dbbd9df6ef41e675a650ebe384b38..d019da73c04d4d206fba22a8d34d8be969674940 100644 >--- a/Source/WebCore/platform/network/ResourceHandleInternal.h >+++ b/Source/WebCore/platform/network/ResourceHandleInternal.h >@@ -51,8 +51,8 @@ > #if USE(SOUP) > #include "GUniquePtrSoup.h" > #include <libsoup/soup.h> >-#include <wtf/gobject/GMainLoopSource.h> > #include <wtf/gobject/GRefPtr.h> >+#include <wtf/gobject/GSourceWrap.h> > #endif > > #if PLATFORM(COCOA) >@@ -168,7 +168,7 @@ namespace WebCore { > GRefPtr<SoupMultipartInputStream> m_multipartInputStream; > GRefPtr<GCancellable> m_cancellable; > GRefPtr<GAsyncResult> m_deferredResult; >- GMainLoopSource m_timeoutSource; >+ GSourceWrap::Static m_timeoutSource; > GUniquePtr<SoupBuffer> m_soupBuffer; > unsigned long m_bodySize; > unsigned long m_bodyDataSent; >diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp >index b7e8c781b75ed9cea9191761bb6afa1c21e4e10a..fda851f9e2b98c78cc2ba860b3e2c59c3330353e 100644 >--- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp >+++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp >@@ -1049,11 +1049,14 @@ void ResourceHandle::sendPendingRequest() > #endif > > if (d->m_firstRequest.timeoutInterval() > 0) { >- d->m_timeoutSource.scheduleAfterDelay("[WebKit] ResourceHandle request timeout", [this] { >- client()->didFail(this, ResourceError::timeoutError(firstRequest().url().string())); >- cancel(); >- }, std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(d->m_firstRequest.timeoutInterval())), >- G_PRIORITY_DEFAULT, nullptr, g_main_context_get_thread_default()); >+ if (!d->m_timeoutSource.isInitialized()) >+ d->m_timeoutSource.initialize("[WebKit] ResourceHandle request timeout", >+ [this] { >+ client()->didFail(this, ResourceError::timeoutError(firstRequest().url().string())); >+ cancel(); >+ }, G_PRIORITY_DEFAULT, g_main_context_get_thread_default()); >+ >+ d->m_timeoutSource.schedule(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(d->m_firstRequest.timeoutInterval()))); > } > > // Balanced by a deref() in cleanupSoupRequestOperation, which should always run.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 138691
:
241857
|
242249
|
242250
|
254639
|
254662
|
256302
|
263833
|
263834