在linux平台下使用Dev_Poll_Reactor 的nofify,一开始使用pipe机制,但是处理不过来,导致死锁。后来改用队列机制,但是第一次抛入的事件并不处理,要等到第二次才处理。以下是ace源码。
int
ACE_Notification_Queue::push_new_notification(
ACE_Notification_Buffer const & buffer)
{
ACE_TRACE ("ACE_Notification_Queue::push_new_notification");
bool notification_required = false;
ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
// No pending notifications.
if (this->notify_queue_.is_empty ())
notification_required = true; //第一次进入时,notify_queue为空,标识为true
if (free_queue_.is_empty())
{
if (allocate_more_buffers() == -1)
{
return -1;
}
}
ACE_Notification_Queue_Node * node =
free_queue_.pop_front();
ACE_ASSERT (node != 0);
node->set(buffer);
notify_queue_.push_back(node);//notify_queue不为空了
if (!notification_required) // 但是 此时标识还是为true的 {
return 0;
}
return 1; // 这里返回。}
int
ACE_Dev_Poll_Reactor_Notify::notify (ACE_Event_Handler *eh,
ACE_Reactor_Mask mask,
ACE_Time_Value *timeout)
{
ACE_TRACE ("ACE_Dev_Poll_Reactor_Notify::notify");
// Just consider this method a "no-op" if there's no
// ACE_Dev_Poll_Reactor configured.
if (this->dp_reactor_ == 0)
return 0;
ACE_Notification_Buffer buffer (eh, mask);
#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
ACE_UNUSED_ARG (timeout);
ACE_Dev_Poll_Handler_Guard eh_guard (eh);
// When using the queue, the push call indicates whether or not a pipe
// write is needed. If it's not, don't waste pipe space.
int push_result = this->notification_queue_.push_new_notification (buffer);
if (-1 == push_result || 1 == push_result)
return -1 == push_result ? -1 : 0; // Also decrement eh's reference count //这里第一次,因为返回1,直接return 0 了,并不往下运行。 // The notification has been queued, so it will be delivered at some
// point (and may have been already); release the refcnt guard.
eh_guard.release ();
// Now pop the pipe to force the callback for dispatching when ready. If
// the send fails due to a full pipe, don't fail - assume the already-sent
// pipe bytes will cause the entire notification queue to be processed.
// Note that we don't need a timeout since the pipe is already in
// nonblocking mode and all we want is one attempt.
ssize_t n = ACE::send (this->notification_pipe_.write_handle (),
(char *) &buffer,
1); // Only need one byte to pop the pipe
if (n == -1 && (errno != EAGAIN))
return -1;
return 0;
#else
ACE_Dev_Poll_Handler_Guard eh_guard (eh);
ssize_t n = ACE::send (this->notification_pipe_.write_handle (),
(char *) &buffer,
sizeof buffer,
timeout);
if (n == -1)
return -1;
eh_guard.release ();
return 0;
#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
}
不解,不知道为什么这么处理? |