skynet学习笔记 sharetable共享表

sharetable特点

1.不同虚拟机共享

2.不可更改

3.脱落gc

4.不可以设置元表

适用场景

不同虚拟机都需要用到的不在代码内更改的配置表

API

sharetable.loadfile(filename,...)

通过文件加载一个lua表,云风大佬推荐使用api

sharetable.loadstring(str)

类似loadfile,loadfile多了一步读取文件

sharetable.loadtable(tbl)

直接共享一张表,云风大佬不推荐,因为此接口会经过一次序列化和拷贝

sharetable.query(filename)

查询共享table

sharetable.update(...)

更新一个或多个key

sharetable.queryall()

查询多个共享表

sharetable更新

sharetable多次load同一张表时会生成多份表数据,只不过query查询永远指向以filename为key的最新加载的数据表地址,所以当你重新loadfile的时候,之前query过的虚拟机指向的是老的filename地址,需要调用sharetable.update更新一下。

sharetable释放

当一个filename被加载多次,老的数据表应该释放,那么何时释放?

sharetable对于每一个数据表都标记了引用计数,当一个虚拟机查询拿到了这个数据表,会使引用计数加1,只有引用计数为0并且不是最新的数据表,才会被释放掉。

    local function query_file(source, filename)
		local m = files[filename]
		local ptr = m:getptr()
		local ref = matrix[ptr]
		if ref == nil then
			ref = {
				filename = filename,
				count = 0,
				matrix = m,
				refs = {},
			}
			matrix[ptr] = ref
		end
		if ref.refs[source] == nil then
			ref.refs[source] = true
			local list = clients[source]
			if not list then
				clients[source] = { ptr }
			else
				table.insert(list, ptr)
			end
			ref.count = ref.count + 1
		end
		return ptr
	end

    function sharetable.close(source)
		local list = clients[source]
		if list then
			for _, ptr in ipairs(list) do
				local ref = matrix[ptr]
				if ref and ref.refs[source] then
					ref.refs[source] = nil
					ref.count = ref.count - 1
					if ref.count == 0 then
						if files[ref.filename] ~= ref.matrix then
							-- It's a history version
							skynet.error(string.format("Delete a version (%s) of %s", ptr, ref.filename))
							ref.matrix:close()
							matrix[ptr] = nil
						end
					end
				end
			end
			clients[source] = nil
		end
		-- no return
	end

何时才能释放引用,需要虚拟机退出,也就是引用过数据表的虚拟机调用skynet.exit()退出了,才能释放引用计数。

local function report_close(t)
	local addr = rawget(t, "address")
	if addr then
		skynet.send(addr, "lua", "close")
	end
end

local sharetable = setmetatable ( {} , {
	__index = load_service,
	__gc = report_close,
})

云风大佬是妙用的__gc原方法的方式调用发送close消息给sharetable,释放掉改虚拟机所以的引用。

你可能感兴趣的:(skynet,skynet,sharetable)