skynet源码 --- queue.lua

  在使用skynet的时候,同一个service,在处理业务时可能出现这种需求:

  1 逻辑A首先在处理,在调用call的时候挂起了当前协程,这时候service收到了退出的消息,需要执行落地操作,这时候A是没有处理完的,这样的结果并不是我们想要的,我们想要的顺序应该是A执行完后,才会执行落地操作并且退出service。

  2 当service的A逻辑与B逻辑都有修改到公共的upvalue时,先执行A逻辑,A逻辑获取到公共的upvalue判断是佛满足后,执行了call操作挂起了当前协程,如果这时候要执行B逻辑,B逻辑获取并修改了公共upvalue,这时候A逻辑等待call返回后,继续获取upvalue值进行操作,可能会出现错误,这时候的理想流程也应当是两个逻辑有使用到公共数据时,应该等待先执行的逻辑执行完才执行后来者。

  3 与2的情况很像,但是更加严重,A逻辑与B逻辑要获取锁的话,可能会出现死锁的情况。

  针对上述问题,必须有一个排队机制,保证先到先执行,执行完成后才继续执行下一个消息。

复制代码
 1 local traceback = debug.traceback
 2 local table = table
 3 
 4 function skynet.queue()
 5     local current_thread
 6     local ref = 0
 7     local thread_queue = {}
 8 
 9     local function xpcall_ret(ok, ...)
10         ref = ref - 1
11         if ref == 0 then
12             current_thread = table.remove(thread_queue,1)
13             if current_thread then
14                 skynet.wakeup(current_thread)
15             end
16         end
17         assert(ok, (...))
18         return ...
19     end
20 
21     return function(f, ...)
22         local thread = coroutine.running()
23         if current_thread and current_thread ~= thread then
24             table.insert(thread_queue, thread)
25             skynet.wait()
26             assert(ref == 0)    -- current_thread == thread
27         end
28         current_thread = thread
29 
30         ref = ref + 1
31         return xpcall_ret(xpcall(f, traceback, ...))
32     end
33 end
34 
35 return skynet.queue
View Code
复制代码

  skyent中实现了queue.lua来保证同一个service中的不同协程的执行顺序。

  使用方式如下,可以直接在service启动时的回调方法里将所有的command入队:

复制代码
 1  function server.on_command(source, cmd, uid, ...)
 2     local fn = command[cmd]
 3     if fn then
 4         if (cmd == "login") then
 5             return fn(source, uid, ...)
 6         end
 7         -- 执行服务指令
 8         local u = onlines[uid]
 9         if u then
10             local umeta = u.umeta
11             local queue = u.queue
12             return queue(fn, source, umeta, ...)
13         else
14             ERROR("agent.command[%s] : user[%s] not exists!!!", cmd, uid)
15         end
16     else
17         ...
18     end
19 end
View Code
复制代码

 

posted @   小乐虎  阅读(355)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示