mahjong_timer.lua
-- -- 麻将高定时器 (Mahjong Timer)-- 基于 数组Map二分查找 实现提供 O(log n) 插入/查找O(n) 删除需移位-- 优化按房间索引表 g_tRoomTimerMap使按房间移除复杂度降为 O(k log n)-- 设计-- - 定时器对象存储在 Map 中键为唯一 TimerID-- - 数组按到期时间升序存储定时器对象的引用同一对象-- - 插入时生成唯一 TimerID二分查找插入位置将对象引用插入数组-- - 删除时通过 TimerID 从 Map 获取对象二分查找其在数组中的位置并移除-- - 房间索引表 g_tRoomTimerMapkey房间IDvalue{ [timerID] true }-- - DoEvents 循环检查数组第一个元素到期则执行回调并移除-- 命名规范全局变量以 g_ 开头局部变量正常表字段带类型前缀-- -- 局部化系统库函数localtable_inserttable.insertlocaltable_removetable.removelocalmath_floormath.floorlocalipairsipairslocalpairspairs-- -- 模块定义-- mahjong_timer{}-- -- 私有数据结构-- --- 定时器对象结构--- field nTimerID integer 唯一定时器ID--- field nExpire integer 到期时间戳毫秒--- field dwRoomID integer 所属房间ID用于按房间移除可选--- field fnCallback function 到期回调函数无参localtTimerNode{nTimerID0,nExpire0,dwRoomID0,fnCallbacknil,}-- 全局私有数据localg_tTimerMap{}-- MapTimerID, tTimerNode 所有定时器对象localg_tSortedTimers{}-- 按 nExpire 升序排列的定时器对象引用数组localg_tRoomTimerMap{}-- Map房间ID, MapTimerID, true 房间索引用于快速按房间移除localg_nNextTimerID1-- 下一个可用的定时器ID自增-- -- 辅助函数二分查找插入位置返回索引该位置及之后的元素应右移-- param nExpire 到期时间戳-- return integer 插入位置的索引1-based-- localfunctionBinarySearchInsertPos(nExpire)localnLow1localnHigh#g_tSortedTimerswhilenLownHighdolocalnMidmath_floor((nLownHigh)/2)localtMidg_tSortedTimers[nMid]iftMid.nExpirenExpirethennLownMid1elseiftMid.nExpirenExpirethennHighnMid-1else-- 相等时也插入在相同 expire 的最后保持稳定性nLownMid1endendreturnnLowend-- -- 辅助函数二分查找指定定时器对象在数组中的位置-- param tTimerNode 定时器对象-- return integer|nil 索引若不存在返回 nil-- localfunctionBinarySearchTimerNode(tTimerNode)localnExpiretTimerNode.nExpirelocalnLow1localnHigh#g_tSortedTimerswhilenLownHighdolocalnMidmath_floor((nLownHigh)/2)localtMidg_tSortedTimers[nMid]iftMid.nExpirenExpirethennLownMid1elseiftMid.nExpirenExpirethennHighnMid-1else-- 找到相同 expire 的区域需要精确匹配对象-- 线性扫描该区域通常数量很少localnStartnMidwhilenStart1andg_tSortedTimers[nStart-1].nExpirenExpiredonStartnStart-1endlocalnEndnMidwhilenEnd#g_tSortedTimersandg_tSortedTimers[nEnd1].nExpirenExpiredonEndnEnd1endforinStart,nEnddoifg_tSortedTimers[i]tTimerNodethenreturniendendreturnnilendendreturnnilend-- -- 辅助函数将定时器ID加入房间索引-- param dwRoomID integer 房间ID-- param nTimerID integer 定时器ID-- localfunctionAddToRoomIndex(dwRoomID,nTimerID)ifdwRoomID0thenreturn-- 不关联房间不加入索引endlocaltRoomTimersg_tRoomTimerMap[dwRoomID]ifnottRoomTimersthentRoomTimers{}g_tRoomTimerMap[dwRoomID]tRoomTimersendtRoomTimers[nTimerID]trueend-- -- 辅助函数从房间索引中移除定时器ID-- param dwRoomID integer 房间ID-- param nTimerID integer 定时器ID-- localfunctionRemoveFromRoomIndex(dwRoomID,nTimerID)ifdwRoomID0thenreturnendlocaltRoomTimersg_tRoomTimerMap[dwRoomID]iftRoomTimersthentRoomTimers[nTimerID]nilifnotnext(tRoomTimers)theng_tRoomTimerMap[dwRoomID]nilendendend-- -- 公共 API创建一次性定时器-- param nDelayMs integer 延迟毫秒数从当前时间开始计算-- param dwRoomID integer 所属房间ID可选用于按房间移除传0表示不关联房间-- param fnCallback function 到期回调函数无参-- return integer nTimerID 定时器ID可用于 CloseTimer-- functionmahjong_timer.CreateTimer(nDelayMs,dwRoomID,fnCallback)iftype(fnCallback)~functionthenerror(mahjong_timer.CreateTimer: callback must be a function)endlocalnNowGetMilliSecond()localnTimerIDg_nNextTimerID g_nNextTimerIDg_nNextTimerID1-- 构造定时器节点localtNode{nTimerIDnTimerID,nExpirenNownDelayMs,dwRoomIDdwRoomIDor0,fnCallbackfnCallback,}g_tTimerMap[nTimerID]tNodeAddToRoomIndex(tNode.dwRoomID,nTimerID)-- 二分查找插入位置localnInsertPosBinarySearchInsertPos(tNode.nExpire)table_insert(g_tSortedTimers,nInsertPos,tNode)returnnTimerIDend-- -- 公共 API关闭指定定时器-- param nTimerID integer 定时器ID-- functionmahjong_timer.CloseTimer(nTimerID)localtNodeg_tTimerMap[nTimerID]ifnottNodethenreturn-- 定时器不存在或已销毁end-- 从房间索引中移除RemoveFromRoomIndex(tNode.dwRoomID,nTimerID)-- 二分查找其在数组中的位置localnIndexBinarySearchTimerNode(tNode)ifnIndexthentable_remove(g_tSortedTimers,nIndex)end-- 从 Map 中删除g_tTimerMap[nTimerID]nilend-- -- 公共 API按房间移除所有定时器-- param dwRoomID integer 房间ID-- functionmahjong_timer.RemoveTimersByRoom(dwRoomID)localtRoomTimersg_tRoomTimerMap[dwRoomID]ifnottRoomTimersthenreturnend-- 收集该房间的所有定时器ID遍历集合localtRemoveIDs{}fornTimerID,_inpairs(tRoomTimers)dotable_insert(tRemoveIDs,nTimerID)end-- 逐个关闭CloseTimer 会更新房间索引因此不能直接在遍历中修改 tRoomTimersfor_,nTimerIDinipairs(tRemoveIDs)domahjong_timer.CloseTimer(nTimerID)end-- 注意CloseTimer 会从 g_tRoomTimerMap 中移除每个 ID最后房间条目会被自动清理end-- -- 公共 API处理到期的定时器每帧调用-- param nNow integer 当前时间戳毫秒通常传入 GetMilliSecond()-- functionmahjong_timer.DoEvents(nNow)-- 循环检查数组第一个元素直到第一个未到期whiletruedolocaltFirstg_tSortedTimers[1]ifnottFirstthenbreak-- 数组为空endiftFirst.nExpirenNowthen-- 到期从数组和 Map 中移除table_remove(g_tSortedTimers,1)-- 从房间索引中移除RemoveFromRoomIndex(tFirst.dwRoomID,tFirst.nTimerID)g_tTimerMap[tFirst.nTimerID]nil-- 执行回调安全调用localbOK,szErrpcall(tFirst.fnCallback)ifnotbOKthen-- 使用全局错误宏需在环境中定义ifMJLOGEthenMJLOGE([MahjongTimer] Callback error: ..tostring(szErr))endendelsebreak-- 第一个未到期停止endendend-- -- 公共 API获取当前定时器数量调试用-- return integer-- functionmahjong_timer.GetTimerCount()return#g_tSortedTimersend
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2423525.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!