ACE_Select_Reactor的Notify功能实现浅析
来源:互联网 发布:手机进程清理软件 编辑:程序博客网 时间:2024/04/30 08:33
ACE_Select_Reactor的Notify功能实现浅析
作者: ydogg 如需转载,请注明但是,为了解决某些特别的原因,如大量的通知存储、规避悬空处理器指针等,ACE也提供了一种有别于Pipe的解决方案,其采用消息排队的方式工作。当采取这种方式时,需定义ACE_HAS_REACTOR_NOTIFICATION_QUEUE宏并重生成ACE。
2. Notify的能力、风险和风险规避
Notify机制最重要的能力是:
1. 让反应器拥有了处理无限处理器的能力
2. 其次是提供了必要时解除反应器事件检查阻塞的能力。
Reactor的notify()让用户直接提供给Reactor待通知反应器的指针,而这些处理器无需注册到反应器上,从而提供了无限的扩展能力。但是,在使用ACE_Pipe的实现中,如果使用不当,可能会造成严重的后果。
潜在的风险:
1. 处理器被销毁后,排队等候的对应通知才被分派
2. ACE_Pipe的数据缓冲是有限的,大量通知到来可能会造成阻塞甚至死锁
不过,在采用队列的Notify实现中,ACE给提供了问题的解决方法。
1. 采用队列方式可无限扩展Notify的数量
2. 采用队列方式为通知的查询提供的方便,因此ACE_Reactor提供puerge_pending_notifications()方法来移除指定的通知,当处理器销毁时,可以使用该方法移除当前队列中所有和自己相关的通知,避免了使用悬空指针。
在采用ACE_Pipe方式中,puerge_pending_notifications()被实现为空方法。
/// sleeping.
ACE_Reactor_Notify *notify_handler_;
7. 实现分析
int restart = 0,
ACE_Sig_Handler * = 0,
ACE_Timer_Queue * = 0,
int disable_notify_pipe = ACE_DISABLE_NOTIFY_PIPE_DEFAULT,
ACE_Reactor_Notify * = 0);
其中ACE_DISABLE_NOTIFY_PIPE_DEFAULT的值为0,表示默认要使用Notify功能。
这个值会传递给ACE_Select_Reactor_Notify的构造函数。在open()的实现中:
{
ACE_NEW_RETURN (this->notify_handler_,
ACE_Select_Reactor_Notify,
-1);
if (this->notify_handler_ == 0)
result = -1;
else
this->delete_notify_handler_ = true;
}
if (result != -1 && this->handler_rep_.open (size) == -1)
result = -1;
else if (this->notify_handler_->open (this,
0,
disable_notify_pipe) == -1)
{
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("%p "),
ACE_TEXT ("notification pipe open failed")));
result = -1;
}
如果没有使用外部的notify时,ACE_Select_Reactor_T将会让notify_handler指向一个new出来的ACE_Select_Reactor_Notify类型的对象,并调用它的open()方法进行初始化。
ACE_Select_Reactor_Notify的open()实现如下(删除了非关键代码):
{
this->select_reactor_ =
dynamic_cast<ACE_Select_Reactor_Impl *> (r);
if (select_reactor_ == 0)
{
errno = EINVAL;
return -1;
}
if (this->notification_pipe_.open () == -1)
return -1;
if (ACE::set_flags (this->notification_pipe_.read_handle (),
ACE_NONBLOCK) == -1)
return -1;
else
return this->select_reactor_->register_handler
(this->notification_pipe_.read_handle (),
this,
ACE_Event_Handler::READ_MASK);
}
else
{
this->select_reactor_ = 0;
return 0;
}
注意,这里的disable_notify_pipe就是ACE_Select_Reactor_T的open()方法中传递的参数,通过它,可以设置不使用notify功能。
可以看出,ACE_Select_Reactor_Notify的open()的主要功能是初始化自己的ACE_Pipe类型成员对象notification_pipe_,并把它注册到Reactor中,监测read事件。
ACE_Pipe的open()实现如下(Win32平台并删除了非关键代码):
ACE_SOCK_Acceptor acceptor;
ACE_SOCK_Connector connector;
ACE_SOCK_Stream reader;
ACE_SOCK_Stream writer;
int result = 0;
# if defined (ACE_WIN32)
ACE_INET_Addr local_any (static_cast<u_short> (0), ACE_LOCALHOST);
# endif
if (acceptor.open (local_any) == -1
|| acceptor.get_local_addr (my_addr) == -1)
result = -1;
else
{
ACE_INET_Addr sv_addr (my_addr.get_port_number (),
ACE_LOCALHOST);
// Establish a connection within the same process.
if (connector.connect (writer, sv_addr) == -1)
result = -1;
else if (acceptor.accept (reader) == -1)
{
writer.close ();
result = -1;
}
}
acceptor.close ();
if (result == -1)
return -1;
this->handles_[0] = reader.get_handle ();
this->handles_[1] = writer.get_handle ();
可以看到,ACE_Pipe通过了一个自身的Tcp连接来模拟Pipe,读写句柄分别就是两端的socket句柄,很巧妙的Pipe移植。而ACE_Pipe的read_handle()函数返回的是handles_[0],也就是说,注册到Reactor是读socket,而handles_[1]将会被客户所使用。
7.2 方法调用
在用户使用notify相关方法时,ACE_Select_Reactor_T充当中介,会将将它们直接交由内部的notify_handler对象处理。
return n == -1 ? -1 : 0;
ACE_Select_Reactor_Nofity的notify()函数代码:
return 0;
ACE_Event_Handler_var safe_handler (event_handler);
if (event_handler)
event_handler->add_reference ();
ACE_Notification_Buffer buffer (event_handler, mask);
ssize_t const n = ACE::send (this->notification_pipe_.write_handle (),
(char *) &buffer,
sizeof buffer,
timeout);
if (n == -1)
return -1;
// No failures.
safe_handler.release ();
这段代码将用户传递的“目的Handler指针“和”掩码“参数,写入了”管道”,实则是通过socket句柄发送了数据。ACE_Notification_Buffer是一个简单的数据包裹类。
7.3 事件分派
Reactor()的事件多路分离流程:
ACE_Reactor::run_reactor_event_loop() -> ACE_Select_Reactor_T::handle_events() ->
ACE_Select_Reactor_T::handle_events_i()
ACE_Select_Reactor_T::handle_events_i()代码如下:
{
// We use the data member dispatch_set_ as the current dispatch
// set.
// We need to start from a clean dispatch_set
this->dispatch_set_.rd_mask_.reset ();
this->dispatch_set_.wr_mask_.reset ();
this->dispatch_set_.ex_mask_.reset ();
int number_of_active_handles =
this->wait_for_multiple_events (this->dispatch_set_,
max_wait_time);
result =
this->dispatch (number_of_active_handles,
this->dispatch_set_);
}
ACE_SEH_EXCEPT (this->release_token ())
{
…
}
Reactor在监测事件时,不区分Noftiy用句柄和其它句柄,一视同仁。所以无需关心wait_for_multiple_events()的实现。
// State has changed or timer queue has failed, exit loop.
break;
if (this->dispatch_notification_handlers
(dispatch_set,
active_handle_count,
other_handlers_dispatched) == -1)
// State has changed or a serious failure has occured, so exit
// loop.
break;
this->dispatch_io_handlers
(dispatch_set,
active_handle_count,
io_handlers_dispatched) == -1)
// State has changed, so exit loop.
break;
可以看出,Select_Reactor分派事件时是按照:定时器、通知、IO事件的顺序进行的。
这里也许有人会疑惑,为什么不直接将notify的处理放在io的分派函数dispatch_io_handlers()中处理呢? 这个想法合情合理,但是Select_Reactor中,规定notify事件的优先级要比普通IO事件的优先级高,以便可以处理一些优先级较高的突发事件。所以必须在IO事件分派前,主动的分派notify事件。并且在notify事件分派后,需要将Pipe的句柄从dispatch_set去除,以免在IO事件分派中被重复分派。
dispatch_notification_handlers()代码:
this->notify_handler_->dispatch_notifications (number_of_active_handles,
dispatch_set.rd_mask_);
if (n == -1)
return -1;
else
{
number_of_handlers_dispatched += n;
number_of_active_handles -= n;
}
ACE_Select_Reactor_T::dispatch_notifications()函数代码:
this->notification_pipe_.read_handle ();
if (read_handle != ACE_INVALID_HANDLE
&& rd_mask.is_set (read_handle))
{
--number_of_active_handles;
rd_mask.clr_bit (read_handle);
return this->handle_input (read_handle);
}
else
return 0;
到了这里,handle_input出现了,下面的处理和ACE_Event_Handler相近了。
ACE_Select_Reactor_Notify::handle_input()函数代码:
int result = 0;
ACE_Notification_Buffer buffer;
while ((result = this->read_notify_pipe (handle, buffer)) > 0)
{
if (this->dispatch_notify (buffer) > 0)
++number_dispatched;
if (number_dispatched == this->max_notify_iterations_)
break;
}
代码逻辑很清楚,从Pipe的缓冲区中依次读取所有接受到的Notify事件信息,并且交给dispatch_notify去处理,如果达到设定值max_notify_iterations_(ACE_Reactor:: max_notify_iterations()函数的功能),就停止分派。
{
ACE_Event_Handler *event_handler = buffer.eh_;
bool const requires_reference_counting =
event_handler->reference_counting_policy ().value () ==
ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
switch (buffer.mask_)
{
case ACE_Event_Handler::READ_MASK:
case ACE_Event_Handler::ACCEPT_MASK:
result = event_handler->handle_input (ACE_INVALID_HANDLE);
break;
case ACE_Event_Handler::WRITE_MASK:
result = event_handler->handle_output (ACE_INVALID_HANDLE);
break;
case ACE_Event_Handler::EXCEPT_MASK:
result = event_handler->handle_exception (ACE_INVALID_HANDLE);
break;
case ACE_Event_Handler::QOS_MASK:
result = event_handler->handle_qos (ACE_INVALID_HANDLE);
break;
case ACE_Event_Handler::GROUP_QOS_MASK:
result = event_handler->handle_group_qos (ACE_INVALID_HANDLE);
break;
default:
// Should we bail out if we get an invalid mask?
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("invalid mask = %d "),
buffer.mask_));
}
if (result == -1)
event_handler->handle_close (ACE_INVALID_HANDLE,
ACE_Event_Handler::EXCEPT_MASK);
}
这里是分派的终点,用户传递的用于处理Notify事件的Handler根据mask的类型而被调用。
8.序列图
- ACE_Select_Reactor的Notify功能实现浅析
- ACE_Select_Reactor
- ACE_Reactor(五)ACE_TP_Reactor和ACE_Select_Reactor的区别
- java的wait和notify方法浅析
- 并发编程-wait,notify实现队列功能
- ACE_Message_Block功能和实现浅析
- ACE_Message_Block功能和实现浅析
- iPhone上关于Push Notify的实现
- thread的wait\notify实现线程通信
- thread的wait\notify实现线程通信
- Wait, notify实现的生产消费模型
- 浅析libvirt的nwfilter功能
- mciSendString 的 notify 功能(播放 结束 后 CallBack)
- 浅析AnyType的实现
- 浅析CROS的实现
- alloc_pages的实现浅析
- Android防止内存溢出浅析/应用自动更新功能的代码实现
- 用ACE_TP_Reactor代替ACE_Select_Reactor
- Linux系统管理、应用与开发实践教程 - 图书目录
- 在MIDP1.0中简单模拟图片翻转功能
- jsp upload package "MultipartRequest and MultipartParser"的license是一本书,呵呵,有趣
- pag 中各属性的介绍(官网.c#)
- 几行代码轻松让你的界面与众不同(for vc)
- ACE_Select_Reactor的Notify功能实现浅析
- RHEL5实现高可用HA集群+GFS+EnterpriseDB
- 数字电路笔试题目1
- UNIX高手的十个习惯
- 英语短语爱情60篇
- Ehcache的配置说明
- 连续自然数之和问题(多种解法)
- Ria介绍
- resin使用mysql的JNDI数据源