Modified: trunk/Source/WebCore/ChangeLog (143209 => 143210)
--- trunk/Source/WebCore/ChangeLog 2013-02-18 14:10:27 UTC (rev 143209)
+++ trunk/Source/WebCore/ChangeLog 2013-02-18 14:28:28 UTC (rev 143210)
@@ -1,3 +1,32 @@
+2013-02-16 Antti Koivisto <[email protected]>
+
+ Reschedule shared CFRunLoopTimer instead of reconstructing it
+ https://bugs.webkit.org/show_bug.cgi?id=109765
+
+ Reviewed by Andreas Kling.
+
+ Using CFRunLoopTimerSetNextFireDate is over 2x faster than deleting and reconstructing timers.
+
+ * platform/SharedTimer.h:
+ (WebCore::SharedTimer::willEnterNestedEventLoop):
+ (WebCore):
+ (MainThreadSharedTimer):
+ (WebCore::MainThreadSharedTimer::willEnterNestedEventLoop):
+ * platform/ThreadTimers.cpp:
+ (WebCore::ThreadTimers::fireTimersInNestedEventLoop):
+ * platform/mac/SharedTimerMac.mm:
+ (WebCore):
+ (WebCore::PowerObserver::clearSharedTimer):
+ (WebCore::ensurePowerObserver):
+ (WebCore::sharedTimer):
+ (WebCore::reinsertSharedTimer):
+
+ Before entering nested runloop (used for inspector debugger mostly) reconstruct and reinsert the timer. For some reason
+ the timer doesn't fire otherwise.
+
+ (WebCore::setSharedTimerFireInterval):
+ (WebCore::stopSharedTimer):
+
2013-02-18 Alexander Pavlov <[email protected]>
Web Inspector: [Resources] Only remember the tree element selection if explicitly made by user
Modified: trunk/Source/WebCore/platform/SharedTimer.h (143209 => 143210)
--- trunk/Source/WebCore/platform/SharedTimer.h 2013-02-18 14:10:27 UTC (rev 143209)
+++ trunk/Source/WebCore/platform/SharedTimer.h 2013-02-18 14:28:28 UTC (rev 143210)
@@ -44,6 +44,7 @@
// The fire interval is in seconds relative to the current monotonic clock time.
virtual void setFireInterval(double) = 0;
virtual void stop() = 0;
+ virtual void willEnterNestedEventLoop() { ASSERT_NOT_REACHED(); }
};
@@ -52,7 +53,9 @@
void setSharedTimerFiredFunction(void (*)());
void setSharedTimerFireInterval(double);
void stopSharedTimer();
-
+#if PLATFORM(MAC)
+ void clearSharedTimer();
+#endif
// Implementation of SharedTimer for the main thread.
class MainThreadSharedTimer : public SharedTimer {
public:
@@ -70,6 +73,13 @@
{
stopSharedTimer();
}
+
+ virtual void willEnterNestedEventLoop()
+ {
+#if PLATFORM(MAC)
+ clearSharedTimer();
+#endif
+ }
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/ThreadTimers.cpp (143209 => 143210)
--- trunk/Source/WebCore/platform/ThreadTimers.cpp 2013-02-18 14:10:27 UTC (rev 143209)
+++ trunk/Source/WebCore/platform/ThreadTimers.cpp 2013-02-18 14:28:28 UTC (rev 143210)
@@ -142,6 +142,7 @@
{
// Reset the reentrancy guard so the timers can fire again.
m_firingTimers = false;
+ m_sharedTimer->willEnterNestedEventLoop();
updateSharedTimer();
}
Modified: trunk/Source/WebCore/platform/mac/SharedTimerMac.mm (143209 => 143210)
--- trunk/Source/WebCore/platform/mac/SharedTimerMac.mm 2013-02-18 14:10:27 UTC (rev 143209)
+++ trunk/Source/WebCore/platform/mac/SharedTimerMac.mm 2013-02-18 14:28:28 UTC (rev 143210)
@@ -42,7 +42,7 @@
namespace WebCore {
-static CFRunLoopTimerRef sharedTimer;
+static const CFTimeInterval distantFuture = 60 * 60 * 24 * 365 * 10; // Decade.
static void (*sharedTimerFiredFunction)();
static void timerFired(CFRunLoopTimerRef, void*);
@@ -143,15 +143,39 @@
{
ASSERT(CFRunLoopGetCurrent() == CFRunLoopGetMain());
- if (!sharedTimer)
- return;
-
stopSharedTimer();
timerFired(0, 0);
}
-static PowerObserver* PowerObserver;
+static void ensurePowerObserver()
+{
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ static PowerObserver* powerObserver;
+ powerObserver = PowerObserver::create().leakPtr();
+ });
+}
+static CFRunLoopTimerRef globalSharedTimer;
+
+static CFRunLoopTimerRef sharedTimer()
+{
+ if (!globalSharedTimer) {
+ globalSharedTimer = CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent() + distantFuture, distantFuture, 0, 0, timerFired, 0);
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), globalSharedTimer, kCFRunLoopCommonModes);
+ ensurePowerObserver();
+ }
+ return globalSharedTimer;
+};
+
+void clearSharedTimer()
+{
+ // For some reason the timer won't fire in a nested runloop unless it has been freshly created and inserted.
+ CFRunLoopTimerInvalidate(globalSharedTimer);
+ CFRelease(globalSharedTimer);
+ globalSharedTimer = 0;
+}
+
void setSharedTimerFiredFunction(void (*f)())
{
ASSERT(!sharedTimerFiredFunction || sharedTimerFiredFunction == f);
@@ -170,27 +194,13 @@
void setSharedTimerFireInterval(double interval)
{
ASSERT(sharedTimerFiredFunction);
-
- if (sharedTimer) {
- CFRunLoopTimerInvalidate(sharedTimer);
- CFRelease(sharedTimer);
- }
-
CFAbsoluteTime fireDate = CFAbsoluteTimeGetCurrent() + interval;
- sharedTimer = CFRunLoopTimerCreate(0, fireDate, 0, 0, 0, timerFired, 0);
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), sharedTimer, kCFRunLoopCommonModes);
-
- if (!PowerObserver)
- PowerObserver = PowerObserver::create().leakPtr();
+ CFRunLoopTimerSetNextFireDate(sharedTimer(), fireDate);
}
void stopSharedTimer()
{
- if (sharedTimer) {
- CFRunLoopTimerInvalidate(sharedTimer);
- CFRelease(sharedTimer);
- sharedTimer = 0;
- }
+ CFRunLoopTimerSetNextFireDate(sharedTimer(), CFAbsoluteTimeGetCurrent() + distantFuture);
}
} // namespace WebCore