webkit中timer实现 分析
1.webkit中timer实现的框架类图
1.1 TimerHeap其实就是一个容器,管理一个一个的Timer
1.2 ThreadTimers 相当于整个timer模块的管理者,负责调度SharedTimer并且操作TimerHeap
1.3 SharedTimer是平台相关的一个类 源码如下:
- public:
- virtual~SharedTimer(){}
- virtualvoidsetFiredFunction(void(*)())=0;
- //ThefiretimeisrelativetotheclassicPOSIXepochofJanuary1,1970,
- //astheresultofcurrentTime()is.
- virtualvoidsetFireTime(double)=0;
- virtualvoidstop()=0;
- };
- //Implementedbyport(sinceitprovidestherunloopforthemainthread).
- //FIXME:makeportsimplementMainThreadSharedTimerdirectlyinstead.
- voidsetSharedTimerFiredFunction(void(*)());
- voidsetSharedTimerFireTime(double);
- voidstopSharedTimer();
- //ImplementationofSharedTimerforthemainthread.
- classMainThreadSharedTimer:publicSharedTimer{
- public:
- virtualvoidsetFiredFunction(void(*function)())
- {
- setSharedTimerFiredFunction(function);
- }
- virtualvoidsetFireTime(doublefireTime)
- {
- setSharedTimerFireTime(fireTime);
- }
- virtualvoidstop()
- {
- stopSharedTimer();
- }
- };
需要设置一个回调函数给底层的Timer,也是通过这个回调,底层timer与上层的结合起来
回调函数是ThreadTimers的一个成员函数,代码如下:
- voidThreadTimers::sharedTimerFiredInternal()
- {
- //Doare-entrancycheck.
- if(m_firingTimers)
- return;
- m_firingTimers=true;
- doublefireTime=currentTime();
- doubletimeToQuit=fireTime+maxDurationOfFiringTimers;
- while(!m_timerHeap.isEmpty()&&m_timerHeap.first()->m_nextFireTime<=fireTime){
- TimerBase*timer=m_timerHeap.first();
- timer->m_nextFireTime=0;
- timer->heapDeleteMin();
- doubleinterval=timer->repeatInterval();
- timer->setNextFireTime(interval?fireTime+interval:0);
- //Oncethetimerhasbeenfired,itmaybedeleted,sodonothingelsewithitafterthispoint.
- timer->fired();
- //Catchthecasewherethetimeraskedtimerstofireinanestedeventloop,orweareovertimelimit.
- if(!m_firingTimers||timeToQuit<currentTime())
- break;
- }
- m_firingTimers=false;
- updateSharedTimer();
- }
通过这个回调,ThreadTimers就从TimerHeap中取出一个个的Timer来执行
1.5 注意Webkit中timer的实现是用模板实现,直接上源代码
- template<typenameTimerFiredClass>classTimer:publicTimerBase{
- public:
- typedefvoid(TimerFiredClass::*TimerFiredFunction)(Timer*);
- Timer(TimerFiredClass*o,TimerFiredFunctionf)
- :m_object(o),m_function(f){}
- private:
- virtualvoidfired(){(m_object->*m_function)(this);}
- TimerFiredClass*m_object;
- TimerFiredFunctionm_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源码:
- #ifndefTimer_h
- #defineTimer_h
- #include<wtf/Noncopyable.h>
- #include<wtf/Threading.h>
- namespaceWebCore{
- //Timeintervalsareallinseconds.
- classTimerHeapElement;
- classTimerBase:publicNoncopyable{
- public:
- TimerBase();
- virtual~TimerBase();
- voidstart(doublenextFireInterval,doublerepeatInterval);
- voidstartRepeating(doublerepeatInterval){start(repeatInterval,repeatInterval);}
- voidstartOneShot(doubleinterval){start(interval,0);}
- voidstop();
- boolisActive()const;
- doublenextFireInterval()const;
- doublerepeatInterval()const{returnm_repeatInterval;}
- voidaugmentRepeatInterval(doubledelta){setNextFireTime(m_nextFireTime+delta);m_repeatInterval+=delta;}
- staticvoidfireTimersInNestedEventLoop();
- private:
- virtualvoidfired()=0;
- voidcheckConsistency()const;
- voidcheckHeapIndex()const;
- voidsetNextFireTime(double);
- boolinHeap()const{returnm_heapIndex!=-1;}
- voidheapDecreaseKey();
- voidheapDelete();
- voidheapDeleteMin();
- voidheapIncreaseKey();
- voidheapInsert();
- voidheapPop();
- voidheapPopMin();
- doublem_nextFireTime;//0ifinactive
- doublem_repeatInterval;//0ifnotrepeating
- intm_heapIndex;//-1ifnotinheap
- unsignedm_heapInsertionOrder;//Usedtokeeporderamongequal-fire-timetimers
- #ifndefNDEBUG
- ThreadIdentifierm_thread;
- #endif
- friendclassTimerHeapElement;
- friendclassThreadTimers;
- friendbooloperator<(constTimerHeapElement&,constTimerHeapElement&);
- };
- template<typenameTimerFiredClass>classTimer:publicTimerBase{
- public:
- typedefvoid(TimerFiredClass::*TimerFiredFunction)(Timer*);
- Timer(TimerFiredClass*o,TimerFiredFunctionf)
- :m_object(o),m_function(f){}
- private:
- virtualvoidfired(){(m_object->*m_function)(this);}
- TimerFiredClass*m_object;
- TimerFiredFunctionm_function;
- };
- inlineboolTimerBase::isActive()const
- {
- ASSERT(m_thread==currentThread());
- returnm_nextFireTime;
- }
- }
- #endif