"In-depth understanding of the use and principles of the Cocos2d-x 3.x" timer (scheduler) (3)

Source: Internet
Author: User

The previous article analyzed the definition of the timer. The point of this article is how the timer is executed.

1. Find the callback for the timer from main

Speaking of the execution of the timer, you have to touch the main function of the COCOS2DX, because the timer is executed on the main thread. is not a separate thread. So its invocation is bound to be called in the main function, every frame.

The following code is the main function under the Win32 platform

int Apientry _tWinMain (hinstance hinstance,                       hinstance hprevinstance,                       LPTSTR    lpcmdline,                       int       nCmdShow) {    unreferenced_parameter (hprevinstance);    Unreferenced_parameter (lpcmdline);    Create the application instance    appdelegate app;    Return Application::getinstance ()->run ();}

Call the run function directly and go directly to the run

int Application::Run () {While    (!glview->windowshouldclose ())    {        QueryPerformanceCounter (&nnow) ;        if (Nnow.quadpart-nlast.quadpart > _animationinterval.quadpart)        {            Nlast.quadpart = Nnow.quadpart-( Nnow.quadpart% _animationinterval.quadpart);                        Director->mainloop ();//See here            glview->pollevents ();        }        else        {            Sleep (1);        }    } return 0;}

Other unrelated calls in the run function I've removed, and I can see that the Mainloop function is the real main loop.

void Displaylinkdirector::mainloop () {    //Do other unrelated things if (! _invalid)    {        drawscene ();    }}
See here is actually calling the Drawscene function

void Director::d rawscene () {    if (! _paused)    {        _scheduler->update (_deltatime);        _eventdispatcher->dispatchevent (_eventafterupdate);    } Before drawing}
DrawsceneThere's so much to do, I'm going to get rid of the drawing part. It is important to note that the drawing scene will not run until after the timer.

As you can see here, the update function of the timer is actually running. So what exactly is running in this update function?

2. The update function of the timer

First look at the code for update

Main loopvoid scheduler::update (float dt) {_updatehashlocked = true;    if (_timescale! = 1.0f) {dt *= _timescale;    }////Timer callback//Tlistentry *entry, *tmp; Queues with priority less than 0 in the update timer first run Dl_foreach_safe (_updatesneglist, entry, TMP) {if ((! entry->paused) &&        (! entry->markedfordeletion))        {entry->callback (dt); }}//Next is the priority equals 0 Dl_foreach_safe (_updates0list, entry, TMP) {if ((! entry->paused) && (!        entry->markedfordeletion)) {entry->callback (dt); }}//finally is greater than 0 dl_foreach_safe (_updatesposlist, entry, TMP) {if ((! entry->paused) && (! en        try->markedfordeletion)) {entry->callback (dt);    }}//Here The loop is itself defined timer for (thashtimerentry *elt = _hashfortimers; ELT! = nullptr;)        {_currenttarget = ELT;        _currenttargetsalvaged = false; if (! _currenttarget->paused) {//Traverse all timers attached to the current object for (Elt->timerindex = 0; Elt->timerindex < Elt->timer s->num; + + (Elt->timerindex)) {Elt->currenttimer = (timer*) (Elt->timers->arr[elt->timerin                Dex]);                elt->currenttimersalvaged = false;//actually run the real callback elt->currenttimer->update (DT) here; if (elt->currenttimersalvaged) {//When the timer finishes the task.                Should release the Elt->currenttimer->release ();            } Elt->currenttimer = nullptr;        }}//point to the next object of the list ELT = (Thashtimerentry *) elt->hh.next; When all the timers for the object have been run.            And the object's attached timer is empty, the object is removed from the hash list if (_currenttargetsalvaged && _currenttarget->timers->num = = 0) {        Removehashelement (_currenttarget); }}//Remove all the update timer elements marked for deletion with a priority of less than 0 dl_foreach_safe (_updatesneglist, entry, TMP) {if(entry->markedfordeletion)        {This->removeupdatefromhash (entry); The update timer element Dl_foreach_safe (_updates0list, entry, TMP) {if (ENTRY-&GT;MARKEDFO)}}//Removed all marked for deletion with priority equal to 0        rdeletion) {This->removeupdatefromhash (entry); }}//Remove all the update timer elements marked for deletion with a priority greater than 0 Dl_foreach_safe (_updatesposlist, entry, TMP) {if (entry->marked        fordeletion) {This->removeupdatefromhash (entry);    }} _updatehashlocked = false; _currenttarget = nullptr;}


There are three parts worth noting:

    1. Update Timer Priority call
    2. The lower the priority of the update timer, the higher the priority call
    3. Self-defined timer callback in elt->currenttimer->update (DT);
On the 3rd, we continue to analyze this update function
void Timer::update (float dt) {///First run will enter into this if initialize if (_elapsed = =-1) {_elapsed = 0;//elapsed Time _timesexe cuted = 0;//Initialization repeated} else {if (_runforever &&!_usedelay) {//cyclic delay function _elapsed +            = DT;            if (_elapsed >= _interval) {trigger ();//Real callback _elapsed = 0;            }} else {//advanced usage _elapsed + = DT; if (_usedelay)//delay {if (_elapsed >= _delay) {trigger ();                    /Real Callback _elapsed = _elapsed-_delay;                    _timesexecuted + = 1;                _usedelay = false;                    }} else//calls {if (_elapsed >= _interval) per frame {                    Trigger ();//Real callback _elapsed = 0; _timesexecuted + = 1;               }}//callback complete, run Cancel function if (!_runforever && _timesexecuted > _repeat)            {//unschedule timer cancel (); }        }    }}

The logic of this large piece of code is clear. The delay function is mainly divided into the delay function of the perpetual cycle and the delay function of the finite cycle. The delay function of the finite loop can be divided into the call of each frame and the fixed time according to the difference of the optimization. The above code is optimized according to this classification.

In fact, the core function

Trigger (); cancel ();
The first function is a real callback function, and the second function is to remove the running function.

void Timertargetselector::trigger () {    if (_target && _selector)    {        (_target->*_selector) (_ elapsed);}    } void Timertargetselector::cancel () {    _scheduler->unschedule (_selector, _target);}

The above is the implementation of the principle of the timer analysis of the whole process, the actual timer is now in the article I feel or say is not very clear. Really go to the code to go through their own should be more clear, for future applications will be more handy.



"In-depth understanding of the use and principles of the Cocos2d-x 3.x" timer (scheduler) (3)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.