Chinaunix首页 | 论坛 | 博客
  • 博客访问: 851227
  • 博文数量: 290
  • 博客积分: 511
  • 博客等级: 下士
  • 技术积分: 1590
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-29 13:14
文章分类

全部博文(290)

文章存档

2018年(28)

2017年(19)

2016年(8)

2015年(1)

2014年(14)

2013年(12)

2012年(22)

2011年(186)

分类:

2011-12-12 14:50:37

作者:gfree.wind@gmail.com
博客:blog.focus-linux.net     linuxfocus.blog.chinaunix.net

好久没碰C++了,感觉真的生疏了,尽力而为吧。


  1. void *zmq_init (int io_threads_)
  2. {
  3.     if (io_threads_ < 0) {
  4.         errno = EINVAL;
  5.         return NULL;
  6.     }

  7.     // Create 0MQ context.
  8.     /* 这里使用的是不抛出异常的new,因为zmq作为库来说,要与不支持异常的调用者兼容,如C。*/
  9.     zmq::ctx_t *ctx = new (std::nothrow) zmq::ctx_t ((uint32_t) io_threads_);
  10.     alloc_assert (ctx);
  11.     return (void*) ctx;
  12. }

  1. zmq::ctx_t::ctx_t (uint32_t io_threads_) :
  2.     /*
  3.     这里使用初始化列表:虽然初始化列表比内部赋值更高效,因为避免了类的一次无谓的构造。但是这里使用的tag     和 terminating是内置类型,不牵涉这个效率问题。
  4.     我想有2个原因:
  5.     1. tag和terminating是ctx_t的特殊一个标志变量,tag是ctx_t的magic cookie,而terminating则是用     于表明该ctx_t是否有效的标志;
  6.     2. 在这个构造函数中的后续部分中,也许某些函数会对这两个标志进行检查;
  7.     这样的话,就不如在初始化列表中,直接给这两个成员变量赋值。
  8.     */
  9.     tag (0xbadcafe0),
  10.     terminating (false)
  11. {
  12.     int rc;

  13.     // Initialise the array of mailboxes. Additional three slots are for
  14.     // internal log socket and the zmq_term thread the reaper thread.
  15.     /*
  16.     这里的max_sockets为一个使用enum方法定义的常量。
  17.     为啥这样,可以参加《More Effective C++》第3版的条款2.
  18.     */
  19.     slot_count = max_sockets + io_threads_ + 3;
  20.     /*
  21.     这里使用了malloc。C++的代码中为啥还要用malloc呢。
  22.     难道就是因为这里只是为了保存maibox_t*,基本类型指针? 
  23.     */
  24.     slots = (mailbox_t**) malloc (sizeof (mailbox_t*) * slot_count);
  25.     alloc_assert (slots);

  26.     // Initialise the infrastructure for zmq_term thread.
  27.     slots [term_tid] = &term_mailbox;

  28.     // Create the reaper thread.
  29.     reaper = new (std::nothrow) reaper_t (this, reaper_tid);
  30.     alloc_assert (reaper);
  31.     
  32.     //......
  33. }

  1. zmq::reaper_t::reaper_t (class ctx_t *ctx_, uint32_t tid_) :
  2.     object_t (ctx_, tid_),
  3.     sockets (0),
  4.     terminating (false)
  5. {
  6.     /* Linux下,poller_t实际上即为epoll_t*/
  7.     poller = new (std::nothrow) poller_t;
  8.     alloc_assert (poller);
     
     /*
     这里的mailbox.get_fd()得到该reaper_t拥有的mailbox的读描述符。
     这里就体现了C++中一项让人不爽的地方——这个描述符是何时赋值的呢?
     首先目前在reaper_t的构造函数中,那么其成员变量mailbox已经执行了默认构造函数,然后mailbox的成员变量
     signaler也执行了默认构造函数,然后在这个构造函数中通过socketpair,得到了两个UNIX域socket pair。
     其中r为读取的socket。
     这里我发表一下自己的看法吧:
     1. 构造函数了作了这么多事,那么构造函数调用的函数失败了怎么办?这时可以说构造函数“失败了”,关于这一      点Scott作了非常好的论述,我就不重复了。在zeromq中,我看到zeromq是不允许任何这样的失败发生,一旦真
     的失败,那么就直接abort了。程序直接挂掉,这种做法对于关键的进程,不一定合适。
     2. 由于很多操作都是在构造函数中做的。也就说明这些调用操作,都是隐式发生的。那么对于代码的阅读者来说,
     阅读代码还是有一些麻烦的。

     也许这个不爽,是因为我很久没有碰C++的代码了吧。
     */
  1.     mailbox_handle = poller->add_fd (mailbox.get_fd (), this);
  2.     。。。。。。
  3. }

  1. zmq::epoll_t::epoll_t () :
  2.     stopping (false)
  3. {
  4.     /* 创建了epoll的描述符 */
  5.     epoll_fd = epoll_create (1);
  6.     errno_assert (epoll_fd != -1);
  7. }

今天就截止到这里,下次继续reaper_t的构造函数。


阅读(733) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~