千两 发表于 2007-12-28 15:13:20

我和咖啡的谈话

伟大的千两 14:50:24
哎呀。问个问题
咖啡 14:51:06

伟大的千两 14:51:00
通信线程和工作线程分开,工作线程负责操作数据库之类的
伟大的千两 14:51:39
例如客户端登陆,通信线程发mb给工作线程,工作线程验证后如何发数据给客户端,你怎么做的
咖啡 14:52:59
工作线程发给通信线程啊
咖啡 14:53:24
都是通信线程发给客户端的
伟大的千两 14:53:04
是不是发给 handler的队列
伟大的千两 14:53:07
但是这里有一个问题
咖啡 14:53:45
可以
伟大的千两 14:53:39
需要激活或者注册svc_handler的writemask
咖啡 14:54:28
你用的通信线程是哪个?
咖啡 14:54:30
reactor?
伟大的千两 14:54:04
对的
咖啡 14:54:49
那就可以开write_mask
伟大的千两 14:54:37
ace的这个操作做了锁保护的
咖啡 14:55:54
write和read它自己保护,不用处理
咖啡 14:56:01
怎么了
伟大的千两 14:55:37
就是因为有锁。所以麻烦了
伟大的千两 14:55:43
我慢慢到来
咖啡 14:56:17

咖啡 14:56:26
貌似很有故事
伟大的千两 14:56:31
客户端A登陆,那么我把A放到MB里发给工作线程对吧
咖啡 14:58:04

伟大的千两 14:57:53
A还在工作线程队列中排队,这个时候A断了,handle_close就清理了数据,并且删除了A
咖啡 14:58:33

咖啡 14:58:49
但是工作线程还会处理是吧
伟大的千两 14:58:28
ACE_Reactor::instance()->schedule_wakeup(pA,ACE_Event_Handler::WRITE_MASK);//tell to write
伟大的千两 14:58:40
但是工作线程并不知道A没了
伟大的千两 14:58:51
所以上面代码会挂
咖啡 14:59:37
工作线程处理之前要判断下
伟大的千两 14:59:15
对。我也是这么想的
咖啡 14:59:59
是啊
咖啡 15:00:10
这个地方要加锁
咖啡 15:00:13
要小心
伟大的千两 14:59:49
于是做了一个登陆list。放进mb的,全部放进list,这个list要加锁
咖啡 15:00:31

伟大的千两 15:00:23
handle_close 如果得到这把锁,立刻干掉自己,并且删除list里面的A
伟大的千两 15:00:26
对吧
咖啡 15:01:07

伟大的千两 15:00:55
这样A在list里面,工作线程发现A没了,知道A被删除了,所以不会错
咖啡 15:01:38

伟大的千两 15:01:21
工作线程判断list的时候也要加锁,防止和handle_close竞争,对否
咖啡 15:02:00
是啊
咖啡 15:02:05
这个list必须加锁
咖啡 15:02:26
一个加一个删,要注意
伟大的千两 15:02:23
一旦工作线程 得到锁,取得A,handle_close 就必须等待不能删除A,直到ACE_Reactor::instance()->schedule_wakeup(pA,ACE_Event_Handler::WRITE_MASK);这个操作完成
伟大的千两 15:02:34
对否
咖啡 15:04:22

咖啡 15:04:31
最多write失败而已
伟大的千两 15:04:05
这就惨了,死锁
咖啡 15:04:44
失败了它也会去删除list
伟大的千两 15:04:30
因为,在任何handle_xxx完成之前ACE_Reactor::instance()要等待,互相等
伟大的千两 15:05:52
你说怎么办,我烦了很久了
咖啡 15:06:32
我的处理list的锁都在外面
咖啡 15:07:08
我分析过这个问题
伟大的千两 15:06:40
锁必须保护到schedule_wakeup(pA,ACE_Event_Handler::WRITE_MASK)完成,不然handle_close干掉A后,工作线程就挂了
伟大的千两 15:06:54
这是一个双向矛盾的问题
伟大的千两 15:07:33
问题在于schedule_wakeup 必须等handle_xxx完成,而handler_close又必须等工作线程完成,死锁!!

Joe 发表于 2008-1-10 23:11:31

例如客户端登陆,通信线程发mb给工作线程,工作线程验证后如何发数据给客户端:
可以通过注册的那个服务的socket收发数据。

A还在工作线程队列中排队,这个时候A断了,handle_close就清理了数据,并且删除了A :
为什么要在handle_close里删除A呢,在工作者线程里判断如果连接断了就mb->release()
页: [1]
查看完整版本: 我和咖啡的谈话