1. webkit中timer实现的框架类图
1.1 TimerHeap其实就是一个容器,管理一个一个的Timer
1.2 ThreadTimers 相当于整个timer模块的管理者,负责调度SharedTimer并且操作TimerHeap
1.3 SharedTimer是平台相关的一个类 源码如下:
- public:
- virtual ~SharedTimer() {}
- virtual void setFiredFunction(void (*)()) = 0;
- // The fire time is relative to the classic POSIX epoch of January 1, 1970,
- // as the result of currentTime() is.
- virtual void setFireTime(double) = 0;
- virtual void stop() = 0;
- };
- // Implemented by port (since it provides the run loop for the main thread).
- // FIXME: make ports implement MainThreadSharedTimer directly instead.
- void setSharedTimerFiredFunction(void (*)());
- void setSharedTimerFireTime(double);
- void stopSharedTimer();
- // Implementation of SharedTimer for the main thread.
- class MainThreadSharedTimer : public SharedTimer {
- public:
- virtual void setFiredFunction(void (*function)())
- {
- setSharedTimerFiredFunction(function);
- }
- virtual void setFireTime(double fireTime)
- {
- setSharedTimerFireTime(fireTime);
- }
- virtual void stop()
- {
- stopSharedTimer();
- }
- };
需要设置一个回调函数给底层的Timer,也是通过这个回调,底层timer与上层的结合起来
回调函数是ThreadTimers的一个成员函数,代码如下:
- void ThreadTimers::sharedTimerFiredInternal()
- {
- // Do a re-entrancy check.
- if (m_firingTimers)
- return;
- m_firingTimers = true;
- double fireTime = currentTime();
- double timeToQuit = fireTime + maxDurationOfFiringTimers;
- while (!m_timerHeap.isEmpty() && m_timerHeap.first()->m_nextFireTime <= fireTime) {
- TimerBase* timer = m_timerHeap.first();
- timer->m_nextFireTime = 0;
- timer->heapDeleteMin();
- double interval = timer->repeatInterval();
- timer->setNextFireTime(interval ? fireTime + interval : 0);
- // Once the timer has been fired, it may be deleted, so do nothing else with it after this point.
- timer->fired();
- // Catch the case where the timer asked timers to fire in a nested event loop, or we are over time limit.
- if (!m_firingTimers || timeToQuit < currentTime())
- break;
- }
- m_firingTimers = false;
- updateSharedTimer();
- }
通过这个回调,ThreadTimers就从TimerHeap中取出一个个的Timer来执行
1.5 注意Webkit中timer的实现是用模板实现,直接上源代码
- template <typename TimerFiredClass> class Timer : public TimerBase {
- public:
- typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*);
- Timer(TimerFiredClass* o, TimerFiredFunction f)
- : m_object(o), m_function(f) { }
- private:
- virtual void fired() { (m_object->*m_function)(this); }
- TimerFiredClass* m_object;
- TimerFiredFunction m_function;
- };
2. webkit中如何应用timer
通过小弟几天的分析,不知正确与否,webkit主要是通过这个timer实现异步,下面以一个场景为例,呈上时序图
场景描述: DOMHTMLParser解析html文档的时候,如果html文档的标签数超过了引擎规定的默认标签且解析时间超过了允许的最长解析时间,会停止解析,通过一个timer异步,之后再timer回调中恢复解析
时序图如下:
timer回调得到执行的时序图如下:
HTMLDocumentSheduler 初始化timer的代码:
- 类成员:Timer<HTMLParserScheduler> m_continueNextChunkTimer;
- 构造函数:
- HTMLParserScheduler::HTMLParserScheduler(HTMLDocumentParser* parser)
- : m_parser(parser)
- , m_parserTimeLimit(parserTimeLimit(m_parser->document()->page()))
- , m_parserChunkSize(parserChunkSize(m_parser->document()->page()))
- , m_continueNextChunkTimer(this, &HTMLParserScheduler::continueNextChunkTimerFired)
- {
- }
这样整个timer模块的设计思路和应用场景就清楚了
3. 系统如何初始化timer模块
神马都是浮云,直接上时序图
Timer源码:
- #ifndef Timer_h
- #define Timer_h
- #include <wtf/Noncopyable.h>
- #include <wtf/Threading.h>
- namespace WebCore {
- // Time intervals are all in seconds.
- class TimerHeapElement;
- class TimerBase : public Noncopyable {
- public:
- TimerBase();
- virtual ~TimerBase();
- void start(double nextFireInterval, double repeatInterval);
- void startRepeating(double repeatInterval) { start(repeatInterval, repeatInterval); }
- void startOneShot(double interval) { start(interval, 0); }
- void stop();
- bool isActive() const;
- double nextFireInterval() const;
- double repeatInterval() const { return m_repeatInterval; }
- void augmentRepeatInterval(double delta) { setNextFireTime(m_nextFireTime + delta); m_repeatInterval += delta; }
- static void fireTimersInNestedEventLoop();
- private:
- virtual void fired() = 0;
- void checkConsistency() const;
- void checkHeapIndex() const;
- void setNextFireTime(double);
- bool inHeap() const { return m_heapIndex != -1; }
- void heapDecreaseKey();
- void heapDelete();
- void heapDeleteMin();
- void heapIncreaseKey();
- void heapInsert();
- void heapPop();
- void heapPopMin();
- double m_nextFireTime; // 0 if inactive
- double m_repeatInterval; // 0 if not repeating
- int m_heapIndex; // -1 if not in heap
- unsigned m_heapInsertionOrder; // Used to keep order among equal-fire-time timers
- #ifndef NDEBUG
- ThreadIdentifier m_thread;
- #endif
- friend class TimerHeapElement;
- friend class ThreadTimers;
- friend bool operator<(const TimerHeapElement&, const TimerHeapElement&);
- };
- template <typename TimerFiredClass> class Timer : public TimerBase {
- public:
- typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*);
- Timer(TimerFiredClass* o, TimerFiredFunction f)
- : m_object(o), m_function(f) { }
- private:
- virtual void fired() { (m_object->*m_function)(this); }
- TimerFiredClass* m_object;
- TimerFiredFunction m_function;
- };
- inline bool TimerBase::isActive() const
- {
- ASSERT(m_thread == currentThread());
- return m_nextFireTime;
- }
- }
- #endif