| Index: Source/platform/Timer.h
|
| diff --git a/Source/platform/Timer.h b/Source/platform/Timer.h
|
| index 58d96925a3673d41573c07d2b4229131645b83ad..59652252f317784d2b6960da579848ce1865f2e8 100644
|
| --- a/Source/platform/Timer.h
|
| +++ b/Source/platform/Timer.h
|
| @@ -43,7 +43,7 @@ public:
|
| TimerBase();
|
| virtual ~TimerBase();
|
|
|
| - void start(double nextFireInterval, double repeatInterval, const TraceLocation&);
|
| + virtual void start(double nextFireInterval, double repeatInterval, const TraceLocation&);
|
|
|
| void startRepeating(double repeatInterval, const TraceLocation& caller)
|
| {
|
| @@ -54,7 +54,7 @@ public:
|
| start(interval, 0, caller);
|
| }
|
|
|
| - void stop();
|
| + virtual void stop();
|
| bool isActive() const;
|
| const TraceLocation& location() const { return m_location; }
|
|
|
| @@ -71,6 +71,9 @@ public:
|
|
|
| static void fireTimersInNestedEventLoop();
|
|
|
| +protected:
|
| + virtual void setNextFireTime(double);
|
| +
|
| private:
|
| virtual void fired() = 0;
|
|
|
| @@ -79,8 +82,6 @@ private:
|
| void checkConsistency() const;
|
| void checkHeapIndex() const;
|
|
|
| - void setNextFireTime(double);
|
| -
|
| bool inHeap() const { return m_heapIndex != -1; }
|
|
|
| bool hasValidHeapPosition() const;
|
| @@ -113,16 +114,99 @@ private:
|
| friend class TimerHeapReference;
|
| };
|
|
|
| +class PLATFORM_EXPORT TimerInstanceTracker {
|
| +public:
|
| + using TraceMethodTrampoline = void (*)(Visitor*, void*);
|
| +
|
| + static void remove(const void*);
|
| + static void add(const void*, TraceMethodTrampoline);
|
| +};
|
| +
|
| +template<typename T, bool = IsGarbageCollectedType<T>::value>
|
| +class TimerKeepAliveTrait {
|
| +public:
|
| + static bool protect(bool, const T*) { return false; }
|
| + static bool unprotect(bool, const void*) { return false; }
|
| +};
|
| +
|
| +#if ENABLE(OILPAN)
|
| +template<typename T>
|
| +class TimerKeepAliveTrait<T, true> {
|
| +public:
|
| + static bool protect(bool needsProtection, const T* object)
|
| + {
|
| + if (needsProtection)
|
| + TimerInstanceTracker::add(object, &trampoline);
|
| +
|
| + return needsProtection;
|
| + }
|
| +
|
| + static bool unprotect(bool doesNotNeedProtection, const void* object)
|
| + {
|
| + if (doesNotNeedProtection)
|
| + TimerInstanceTracker::remove(object);
|
| +
|
| + return doesNotNeedProtection;
|
| + }
|
| +
|
| +private:
|
| + static void trampoline(Visitor* visitor, void* self) { (reinterpret_cast<T*>(self)->trace)(visitor); }
|
| +};
|
| +#else
|
| +// FIXME: Oilpan: remove this specialization when lazy sweeping is enabled on trunk.
|
| +template<typename T>
|
| +class TimerKeepAliveTrait<T, true> {
|
| +public:
|
| + static bool protect(bool, const T*) { return false; }
|
| + static bool unprotect(bool, const void*) { return false; }
|
| +};
|
| +#endif
|
| +
|
| template <typename TimerFiredClass>
|
| class Timer final : public TimerBase {
|
| public:
|
| typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*);
|
|
|
| Timer(TimerFiredClass* o, TimerFiredFunction f)
|
| - : m_object(o), m_function(f) { }
|
| + : m_object(o)
|
| + , m_function(f)
|
| + , m_isKeptAlive(false)
|
| + {
|
| + }
|
| +
|
| + ~Timer() override
|
| + {
|
| + TimerKeepAliveTrait<TimerFiredClass>::unprotect(m_isKeptAlive, m_object);
|
| + }
|
| +
|
| + void start(double nextFireInterval, double repeatInterval, const TraceLocation& caller) override
|
| + {
|
| + TimerBase::start(nextFireInterval, repeatInterval, caller);
|
| + if (TimerKeepAliveTrait<TimerFiredClass>::protect(!m_isKeptAlive && isActive(), m_object))
|
| + m_isKeptAlive = true;
|
| + }
|
| +
|
| + void stop() override
|
| + {
|
| + TimerBase::stop();
|
| + if (TimerKeepAliveTrait<TimerFiredClass>::unprotect(m_isKeptAlive && !isActive(), m_object))
|
| + m_isKeptAlive = false;
|
| + }
|
|
|
| private:
|
| - virtual void fired() override { (m_object->*m_function)(this); }
|
| + void fired() override
|
| + {
|
| + if (TimerKeepAliveTrait<TimerFiredClass>::unprotect(m_isKeptAlive && !isActive(), m_object))
|
| + m_isKeptAlive = false;
|
| + (m_object->*m_function)(this);
|
| + }
|
| +
|
| + void setNextFireTime(double newUnalignedTime) override
|
| + {
|
| + TimerBase::setNextFireTime(newUnalignedTime);
|
| + if (TimerKeepAliveTrait<TimerFiredClass>::unprotect(m_isKeptAlive && !isActive(), m_object))
|
| + m_isKeptAlive = false;
|
| + }
|
|
|
| // FIXME: oilpan: TimerBase should be moved to the heap and m_object should be traced.
|
| // This raw pointer is safe as long as Timer<X> is held by the X itself (That's the case
|
| @@ -130,6 +214,7 @@ private:
|
| GC_PLUGIN_IGNORE("363031")
|
| TimerFiredClass* m_object;
|
| TimerFiredFunction m_function;
|
| + bool m_isKeptAlive;
|
| };
|
|
|
| inline bool TimerBase::isActive() const
|
| @@ -138,6 +223,6 @@ inline bool TimerBase::isActive() const
|
| return m_nextFireTime;
|
| }
|
|
|
| -}
|
| +} // namespace blink
|
|
|
| -#endif
|
| +#endif // Timer_h
|
|
|