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
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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)