读者来信与解答 1

读者来信用黑色,个人回答用蓝色。通过整理,接近对话体。api


> 陈硕,你好,
>
> 阅读了你的书,颇有收获。
> 可是没有在moduo的源代码里面找到实现线程模型11的例子。即one thread per loop + thread pool。
> 谢谢。函数

书第 173 页图 6-14 下面的第一段话,具体改动方法参考前一页的 diff。oop


> 谢谢。
>
> 另外TcpConnection和Channel的生命周期管理有点问题。
> TcpConnection若是已经被回收了,其包含的Channel也已经被回收了。而这个时候在Channel::handleEvent()里面检查tied_和tie_是危险的。由于其内存已经被回收了。
>
> 若是用户保证TcpConnection被回收以后,不会再用Channel的裸指针,则没有必要在TcpConnection::connectEstablished()中call tie().优化

TcpConnection 回收以前,会调用 connectDestroyed,其中调用 channel_->remove();,这样就不可能再会有 Channel::handleEvent() 被调用了。ui

tie() 的做用是防止 Channel::handleEvent() 运行期间其 owner 对象析构,致使 Channel 自己被销毁。线程


> > TcpConnection 回收以前,会调用 connectDestroyed,其中调用 channel_->remove();,这样就不可能再会有 Channel::handleEvent() 被调用了
> 这个时候会不会有race condition?假设如今有两个active channels,处理头一个的时候回收TcpConnection,而第二个channel恰好对应这个connection。debug

这时你没有办法强制销毁 TcpConnection,只能下降其引用计数,因此不会有问题。你能够写段代码试试。指针

> 另外底层的poller OS api是否保证unregister channel以后必定不会再有这个channel的事件,会清空内核的已经就绪的事件队列?对象

跟内核不要紧,Poller class 在 unregister channel 以后就不可能调用其 handleEvent() 成员函数。生命周期

> 那EPollPoller::fillActiveChannels()的改一改,“assert(it != channels_.end());”再也不适用了,并且每次都个event都要查一次map。效率会有问题。

assert() 只有在 debug build 才执行,不会影响效率。
再说每一个 event 都要涉及 read/write 等系统调用,开销比“查一次 map”大得多,优化这里是无用功。

> 但这个assert()不是invalid了吗?你可能以前在unregister channel的时候已经从map里面remove掉了它。

这个 assert 是有效的,你再想一想。


> > tie() 的做用是防止 Channel::handleEvent() 运行期间其 owner 对象析构,致使 Channel 自己被销毁。

> 这个也不太make sense。仍然有race conditon。在Channel::handleEvent()拥有guard锁定ownner以前,Channel::handleEvent()须要检查其tied_。

你再想一想,tie 的做用是防止调用 handleEvent() 期间对象销毁(好比调用 closeCallback 期间),不是也不可能防止调用 handleEvent() 以前对象销毁。

> 恩,是的。整个TcpConnection, Channel, EventLoop都是一个thread里面run的。

相关文章
相关标签/搜索