Archive for 六月 2013

qnode 0.1发布

大概半年前提到的qnode项目,实际上我在这半年里一直不停的ci代码。不过最近改变思路,决定时不时发布一个小版本,包含几个新的特性,有点类似互联网产品中的快速发布敏捷迭代。这样的好处是,其他人能看到这个项目的进度,我也有一个比较明确的短期目标去开发。

0.1版本主要做的是这几件事情:

shared_ptr和对象管理

异步的分布式编程常遇到一个问题。比如某个客户端连接上来之后,发送的请求业务逻辑处理是需要服务器再连接到另外一个服务器做查询的,那么有可能出现的情况是,这个回复的时间太长或者各种其他原因,客户端在处理完毕之前主动关闭连接了,导致从另一台服务器处理完毕的时候,该连接指针已经失效。

这个问题很常见,尤其在业务复杂,异步的环境下更容易出现了。

简单的来理解,需要一个机制,在处理完毕的时候查询到该连接指针是不是有效的。

我想的第一个策略是使用shared_ptr管理这个连接,然后用一个该shared_ptr的weak_ptr来观察该指针是否还有效。然而shared_ptr是一种具备传染性的策略:某个指针一旦某处使用shared_ptr管理,那么所有该指针出现的地方也需要使用shared_ptr了。我不认为这是一个好办法。

咨询了另一个我比较信服的朋友,给的方法是不再传递指针,而是使用ID。换言之,ID和这个指针是一一对应的关系,处理完毕之后要向该连接回复的时候,首先根据ID来查询该连接是不是还有效,然后再做后面的事情。

这个思路我认同。不过细化起来还有几点需要考虑的。ID如何分配,是使用连接的FD么?这样带来的问题是,操作系统实际上会很快复用刚才关闭的FD,会有一定的风险。我最后使用的策略是分配ID的地方保存一个计数,每次加一,使用STL的map来管理ID和指针的对应关系,在新分配一个ID之前,虽然将原来的计数器加一了,但是也要判断是不是原来这个ID已经有对应的指针与之绑定了。

第二个问题是,管理ID对应关系的管理器是全局只有一个吗?如果只有一个,那么在多线程环境下势必需要加锁操作。由于我现在做的这个服务器是多线程,每个线程绑定了一个epoll,所以策略变为每个线程一个ID管理器,同时ID中带上线程的信息,比如使用低两位保存线程的ID,这样就可以根据ID识别出来这个ID属于哪个线程管理的。于是由于给线程发消息的消息队列有先后顺序,比如前一个消息说删除这个ID,后一个消息给这个ID发送消息,那么后一个消息就不会被处理,因为ID已经被删除了。

我个人觉得这种方案,比直接在各种线程里使用指针,同时使用shared_ptr来管理的方案,要好的多。

Lua5.1.4代码分析(二十二)-表的赋值和查询

这里涉及到的两个OPCODE,SETTABLE和GETTABLE,由名字可以知道,分别用于表的赋值和查询。
两个OPCODE指令格式如下:

OP_SETTABLE,/*  A B C R(A)[RK(B)] := RK(C)        */
OP_GETTABLE,/*  A B C R(A) := R(B)[RK(C)]      

Lua5.1.4代码分析(二十一)-表的创建和初始化

在讲解之前,先来简单回顾一下Lua表的初始化语法。

在Lua中,表是唯一的数据结构,可以使用它,模拟hash表,数组,链表,树等一切常用的数据结构。Lua表分为数组部分和hash部分。比如:

local t = {1,2,3,4,5}

以上分配一个Lua数组,依次为1到5.

而如果要初始化hash部分,则需要指定key,有两种方式:

local t = {a="test"}
local t =