Skynet's pseudo-Cancel timer

Source: Internet
Author: User

1. As of now, members of the group have made additional requests for timeout in Skynet. Currently the timer provided by Skynet is a countdown form, and once the timer is set, it cannot be revoked (at least for the current implementation), and then the CB is called

It has recently been suggested that it is possible to support the function of the undo timer, but the cloud insists: "The framework should only provide the essential features that can be removed from what has been achieved with existing features."

2. Why do we say pseudo-Cancel timer?

In Skynet, when Skynet.timeout (time, CB) is called, it goes into skynet_timer.c management, and then, after that time, the message is placed on the calling service's message queue, waiting for the callback function to process.

The real cancellation timer is when the party calls the cancel timer interface, stops the countdown and deletes the task from somewhere, as if nothing had happened.

Then the pseudo-cancellation is the countdown to continue execution, only when the callback function execution after the countdown, not the callback registered when the call timer, but the change of the callback, this callback does not do anything, thereby implementing pseudo-cancellation.

3. The idea of pseudo-cancellation timer

First look at the Skynet.timeout ().

function Skynet.timeout (Ti, func)     = C.intcommand ("TIMEOUT", Ti)    assert (session)    = co_create (func)     = = Nil    )= Co    return  sessionend

1) use "TIMEOUT" command to start this countdown, and return a session, and then use the back function to create a co-process, create the following code:

Local functionco_create (f)LocalCO =Table.remove(Coroutine_pool)ifCO = =Nil  ThenCo=coroutine.create(function(...)            F (...)  while true  DoF=Nilcoroutine_pool[#coroutine_pool +1] =Co F= Coroutine_yield"EXIT"f (Coroutine_yield ())End        End)    ElseCoroutine_resume (Co, F)End    returnCoEnd

For the pool in this virtual machine, Coroutine_pool will only be used in this function, that is, if the pool is empty, then use F to create a new co-process and put it in the pool, if there is a co-re-registration callback function F.

2) use session_id_coroutine[session] = Co to save the relationship between the session and Co, and when the countdown is over, the session will be based on Co. The timeout function ends here, and then it looks like the framework can be used to implement the callback after the countdown is over. Seems to have done nothing, the real mystery in

Local session = C.intcommand ("TIMEOUT", TI).

The hand has the source code can directly follow in, see what exactly did.

So where is the call to the callback? In Skynet.draw_dispatch_message (...) In

functionskynet.dispatch_message (...) LocalSUCC, err =Pcall(Raw_dispatch_message,...)  while true  Do        LocalKey,co =Next(Fork_queue)ifCO = =Nil  Then             Break        EndFork_queue[key]=Nil        LocalFORK_SUCC, Fork_err =Pcall(Suspend,co,coroutine_resume (CO))if  notFork_succ Then            ifSucc Thensucc=falseErr=ToString(Fork_err)ElseErr=ToString(ERR):"\ n"..ToString(Fork_err)End        End    End    assert(SUCC,ToString(err))EndLocal functionRaw_dispatch_message (prototype, MSG, SZ, session, source)--Skynet. Ptype_response = 1, read skynet.h    ifPrototype = =1  Then        LocalCO =Session_id_coroutine[session]ifCO = =" Break"  ThenSession_id_coroutine[session]=Nil        ElseIfCO = =Nil  Then            Print("prototype, MSG, SZ, session, Source:", prototype, MSG, SZ, session, Source) Unknown_response (session, source, MSG, SZ)ElseSession_id_coroutine[session]=Nilsuspend (CO, Coroutine_resume (CO,true, MSG, SZ)) End    Else        Localp =Proto[prototype]ifp = =Nil  Then            ifSession ~=0  Thenc.send (source, Skynet. Ptype_error, Session,"")            ElseUnknown_request (session, source, MSG, SZ, prototype)End            return        End        Localf =P.dispatchifF Then            Localref =Watching_service[source]ifRef ThenWatching_service[source]= ref +1            ElseWatching_service[source]=1            End            LocalCO =co_create (f) Session_coroutine_id[co]=session Session_coroutine_address[co]=Source Suspend (CO, Coroutine_resume (CO, Session,source, p.Unpack(MSG,SZ))) ElseUnknown_request (session, source, MSG, SZ, proto[prototype].name)End    EndEnd

The logic of the yellow code is executed when the countdown is complete:

Session_id_coroutine[session] = Nil

suspend (CO, Coroutine_resume (CO, true, MSG, SZ))

At this point the Co is obtained from the session, and the Co is the callback process.

As mentioned earlier, to cancel is a co that is replaced with nothing until the time of the CO is done. The key to replacement: 1. Desession;2 The first time timeout, regenerate a co. Both of these points can be implemented in Skynet.lua, with the following code:

Local functionREMOVE_TIMEOUT_CB (...)EndfunctionSkynet.remove_timeout (session)LocalCO =co_create (REMOVE_TIMEOUT_CB)assert(Session_id_coroutine[session] ~=Nil) Session_id_coroutine[session]=CoEndfunctionskynet.timeout (Ti, func)LocalSession = C.intcommand ("TIMEOUT", TI)assert(session)LocalCO =Co_create (func)assert(Session_id_coroutine[session] = =Nil) Session_id_coroutine[session]=CoreturnSessionEnd

As you can see, the Skynet.remove_timeout and SKYNET.REMOVE_TIMEOUT_CB () are added, and the obtained session is returned in Skynet.timeout (). The code is very simple, just follow the previous ideas to achieve.

4. Test the code:

Local session = Skynet.timeout ("test Timeout 10  end) Skynet.remove_timeout (session) Skynet.timeout (function  Print("test timeout"end)

5. Test process:

1) Modify the Skynet.lua, add Skynet.remove_timeout and SKYNET.REMOVE_TIMEOUT_CB (), and make the Skynet.timeout return the resulting session.

2) Modify the configuration file Config,start = "Testtimer" To change the start script to test Testtimmer, where the test will be performed.

3) Use the top three test code in Skynet.start in Testtimer.lua, or write it yourself to get the results.

To this, a skyent pseudo-cancellation timer was implemented. Of course can be passed to similar c. Initcommand ("TIMEOUT", T1) in this form, the implementation of their own "remove_timeout" command, only such changes in more places, but can achieve a complete cancellation.

A temporary cancellation was implemented today and a new command is being created to completely cancel. It is hereby recorded that you are welcome to correct and advise.

  

Skynet's pseudo-Cancel timer

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.