skynet 定時器sleep與fork

在前面的幾篇中定時器其實我們已經(jīng)應(yīng)用過了,入口函數(shù)就是靠定時器驅(qū)動的,只不過他的定時為0.參見skynet lua業(yè)務(wù)邏輯的啟動--skynet.start() .

在后面的服務(wù)與服務(wù)交互中,為了保證在A服務(wù)call B服時,B服務(wù)已經(jīng)啟動,我們特意在A服務(wù)call前執(zhí)行了一個無意義的循環(huán).這節(jié)中的定時器就可以解決這個問題,調(diào)用skynet.sleep(xxx)就可以讓協(xié)程掛起.我們看看sleep的代碼:

function skynet.sleep(ti)
    local session = c.intcommand("TIMEOUT",ti)            --①
    assert(session)
    local succ, ret = coroutine_yield("SLEEP", session)   --②
    sleep_session[coroutine.running()] = nil
    if succ then
        return
    end
    if ret == "BREAK" then
        return "BREAK"
    else
        error(ret)
    end
end

①處會調(diào)用c的timeout接口,前面講過.由于ti不為0,那么他會在c中注冊一個定時器事件,等定時器超時,他會push一個PTYPE_RESPONSE類型,包含session的消息.(c中怎么調(diào)度定時器另起一篇再介紹)

②處導(dǎo)致正在執(zhí)行的協(xié)程掛起,這會讓corutine.resume返回去執(zhí)行suspend.

suspend()函數(shù)中'sleep'命令的處理只是關(guān)聯(lián)了兩個表,一個用co作key,session作value,另一個以session作key,co作value.他們的作用是,當(dāng)收到定時器消息時能夠快速找到關(guān)聯(lián)的協(xié)程co,并恢復(fù)該協(xié)程co,這樣經(jīng)sleep掛起的協(xié)程就又恢復(fù)了.

注意skynet.sleep()參數(shù)是以100為單位,即100表示一秒.

skynet.sleep()應(yīng)該很好理解,再來稍難點的.有這樣一個需求:如何像linux c 一樣創(chuàng)建兩個線程,然后獨自運行線程函數(shù).skynet提供了skynet.fork(),一個例子如下:

skynet.start(function()

    function myfork( val )
        while true do
            print('myfork ', val, ' !!!! ')
            skynet.sleep(200)
        end
    end
    local co1 = skynet.fork(myfork, 1)
    local co2 = skynet.fork(myfork, 2)

end)

運行結(jié)果為:

1fa40c805a061e1d82ab13bbbd545f3a_70.png

可以看到兩個'線程函數(shù)'交替的運行了,我們來分析一下:

function skynet.fork(func,...)
    local args = { ... }
    local co = co_create(function()
        func(tunpack(args))
    end)
    table.insert(fork_queue, co)
    return co
end

可以看到fork實際上是創(chuàng)建了一個協(xié)程函數(shù),并插入到表里,那什么時候開始執(zhí)行協(xié)程函數(shù)呢?

我們追溯fork_queue,發(fā)現(xiàn)他是在skynet.dispatch_message()被執(zhí)行的:

function skynet.dispatch_message(...)
    local succ, err = pcall(raw_dispatch_message,...)
    while true do
        local key,co = next(fork_queue)      --表示獲取表的第一個元素和key,t={12,a=34,5,c}都可以訪問到
        if co == nil then
            break
        end
        fork_queue[key] = nil
        local fork_succ, fork_err = pcall(suspend,co,coroutine.resume(co))
        if not fork_succ then
            if succ then
                succ = false
                err = tostring(fork_err)
            else
                err = tostring(err) .. "\n" .. tostring(fork_err)
            end
        end
    end
    assert(succ, tostring(err))
end

我們看到必須要等到skynet.raw_dispatch_message函數(shù)執(zhí)行完成.

結(jié)合前面的幾篇文章分析,必須等到skynet.raw_dispatch_message()里的suspend函數(shù)執(zhí)行完畢.而suspend函數(shù)開始執(zhí)行要等到coroutine.resume()返回.所以必須等到執(zhí)行中的協(xié)程掛起,才有機會執(zhí)行fork里的協(xié)程了.

要想執(zhí)行中的協(xié)程被掛起,除了調(diào)用skynet.sleep()之外,當(dāng)前消息回調(diào)函數(shù)執(zhí)行完畢也會調(diào)用coroutine_yield "EXIT",參看前面講解co_create()的部分.

需要注意的是,在lua里多個協(xié)程函數(shù)不可能像linux c多線程一樣真正同時執(zhí)行,同一時間只有一個協(xié)程函數(shù)在執(zhí)行,只不過利用協(xié)程調(diào)度,可以做到同時執(zhí)行的假象罷了.

所以當(dāng)一個協(xié)程里執(zhí)行死循環(huán)時,另一個協(xié)程時不可能有機會再執(zhí)行的,這點千萬要注意!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亿扁,一起剝皮案震驚了整個濱河市瓦宜,隨后出現(xiàn)的幾起案子粹排,更是在濱河造成了極大的恐慌嗅义,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件答倡,死亡現(xiàn)場離奇詭異纵势,居然都是意外死亡步清,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門榜晦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冠蒋,“玉大人,你說我怎么就攤上這事乾胶《督耍” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵识窿,是天一觀的道長斩郎。 經(jīng)常有香客問我,道長喻频,這世上最難降的妖魔是什么缩宜? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮甥温,結(jié)果婚禮上锻煌,老公的妹妹穿的比我還像新娘膜宋。我一直安慰自己,他們只是感情好炼幔,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布秋茫。 她就那樣靜靜地躺著,像睡著了一般乃秀。 火紅的嫁衣襯著肌膚如雪肛著。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天跺讯,我揣著相機與錄音枢贿,去河邊找鬼。 笑死刀脏,一個胖子當(dāng)著我的面吹牛局荚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愈污,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼耀态,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了暂雹?” 一聲冷哼從身側(cè)響起首装,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎杭跪,沒想到半個月后仙逻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡涧尿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年系奉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姑廉。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡缺亮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出庄蹋,到底是詐尸還是另有隱情瞬内,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布限书,位于F島的核電站虫蝶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏倦西。R本人自食惡果不足惜能真,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粉铐,春花似錦疼约、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至汤踏,卻和暖如春织鲸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背溪胶。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工搂擦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哗脖。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓瀑踢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親才避。 傳聞我的和親對象是個殘疾皇子橱夭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容