博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过 skynet 学习到的 assert 的使用
阅读量:6412 次
发布时间:2019-06-23

本文共 1970 字,大约阅读时间需要 6 分钟。

hot3.png

assert 用于断言某条件必须成立,否者就会触发断言失败,比如在 C 中进程会退出并打印出行号,而 Lua 中打印出 traceback 。

有时候会听人说要学会使用 assert 。当时并不理解,因为 assert 就是断言某条件必须成立,很简单啊,怎么还特别强调要学会呢。直到后来看见关于 skynet 的多线程读写的 后,才体会到 assert 的用法,就是使用 assert 来限定代码的边界,掌控代码的执行,如果 assert 断言失败,可以很明确代码问题所在。

skynet 的 产生原因如下。在 中,有用户无法编译通过,于是云大在之后做了些,将 uint64_t sending 修改为 uint32_t sending 来确保在某些平台能编译通过。但是解决 后,没有想到触发了 assert 断言失败,产生了 。这里就想简单介绍一下,在解决 时增加的 assert 代码。

先说修复 编译不通过前,多线程写 socket 的实现。云大在中上传了 skynet 支持多线程写入代码。一开始定义就是 uint64_sending 被分成两部分,高 32 位是分配的 id,低 32 位表示 socket 线程中此 id 正在发送的包数量,若低 32 位为 0,则表示此时 socket 线程中还未有需要发送的数据。所以 service 需要发送数据时,在 worker 线程调用 socket_server_send 函数,此时若能直接 write 则直接调用 write 写入数据,若不能直接 write 则会增加 sending 计数,通过 socket 线程发送,发送完毕后减少 sending 计数。

在多线程写 socket 实现提交后,产生了 存在某些平台上编译不通过,于是云大改成了 uint32_t sending 。这里有一个技巧是 skynet 分配的 socket id 是递增的,具体实现见 reserve_id 函数,而且 id 被 HASH_ID 的 hash 处理也只是求余操作,那么如果 slot 1 被占用,就不会存在第二个被使用的 HASH_ID(id) 为 1 的 socket id 。所以通过 ID_TAG16 取出 slot 进而判断 socket_server.slot 是否被使用了,于是 sending 的高 16 位用于标识 id 对应的 slot 而低 16 位用于计数。这里就存在了一个前提,计数的最大值是 65535 。所以云大在中的第 571 行加了 assert 确保计数一超过 65535 就会断言失败。真的有情景触发了断言失败,然后就产生了前文提到的的 问题。由于 bug 触发了 assert 断言失败,于是可以目的很明确的修复这个问题。话说回来,多线程写 socket 还真是挺复杂的。

其实 Lua 的代码中也在很多地方用了 assert 。不过 Lua 代码比较复杂,这里再举个例子,比如 skynet 中的 skynet.queue 模块,其中有用 assert 。位于 skynet/lualib/skynet/queue.lua 文件。部分代码如下。

function skynet.queue()	local current_thread	local ref = 0	local thread_queue = {}	return function(f, ...)		local thread = coroutine.running()		if current_thread and current_thread ~= thread then			table.insert(thread_queue, thread)			skynet.wait()			assert(ref == 0)	-- current_thread == thread		end		current_thread = thread		ref = ref + 1		return xpcall_ret(xpcall(f, traceback, ...))	endend

其中 assert(ref == 0) 确保之前的 current_thread 已经执行完毕。注意,当在同一个 coroutine 中嵌套调用时 ref 是可能大于 1 的。如。

local lock = skynet.queue()lock(function()	print("one")	lock(function()		print("two")	end)end)

总之 assert 真的是个好东西。

转载于:https://my.oschina.net/iirecord/blog/1648176

你可能感兴趣的文章
分享Silverlight新鲜事 - Silverlight Firestarter全球会议
查看>>
产品设计体会(3013)项目的“敏捷沟通”实践
查看>>
RHEL6.3基本网络配置(1)ifconfig命令
查看>>
网络诊断工具之—路由追踪tracert命令
查看>>
Java模拟HTTP的Get和Post请求(增强)
查看>>
php 环境搭建(windows php+apache)
查看>>
让虚拟机的软盘盘符不显示(适用于所有windows系统包括Windows Server)
查看>>
Cygwin不好用
查看>>
jQuery插件之验证控件jquery.validate.js
查看>>
[经验]无线鼠标和无线键盘真的不能用了?——雷柏的重生之路~
查看>>
【转】plist涉及到沙盒的一个问题
查看>>
GNU make manual 翻译( 一百四十五)
查看>>
重构之美-走在Web标准化设计的路上[复杂表单]3 9 Update
查看>>
linux中的优先搜索树的实现--prio_tree【转】
查看>>
转载: 打造自己的asp.net验证控件
查看>>
重构之美-跨越Web标准,触碰语义网[开门见山:Microformat]
查看>>
git入门与实践【转】
查看>>
WPF 虚拟键盘
查看>>
储存卡无法打开专家教您怎么数据恢复
查看>>
彼得原理
查看>>