1. ACE_Reactor的創(chuàng)建
ctor: ACE_Reactor (ACE_Reactor_Impl *implementation = 0, int delete_implementation = 0);
你可以自己創(chuàng)建一個(gè)ACE_Reactor
但是大多數(shù)時(shí)候,我們都是通過調(diào)用ACE_Reactor::instance()這個(gè)靜態(tài)方法來返回唯一的實(shí)例。
ACE_Reactor *
ACE_Reactor::instance (void)
{
ACE_TRACE ("ACE_Reactor::instance");
if (ACE_Reactor::reactor_ == 0) //1
{
// Perform Double-Checked Locking Optimization.
ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
*ACE_Static_Object_Lock::instance (), 0));
if (ACE_Reactor::reactor_ == 0) //2
{
ACE_NEW_RETURN (ACE_Reactor::reactor_,
ACE_Reactor,
0);
ACE_Reactor::delete_reactor_ = 1;
ACE_REGISTER_FRAMEWORK_COMPONENT(ACE_Reactor, ACE_Reactor::reactor_)
}
}
return ACE_Reactor::reactor_;
}
注意這點(diǎn)使用了雙檢測(cè)的機(jī)制(代碼1和2),為了提高效率,不用每次都加鎖。
2. Impl手法的運(yùn)用
ACE_Reactor有個(gè)成員變量 ACE_Reactor_Impl *implementation_;
這個(gè)implementation_才是真正做事情的東西,典型的Impl手法。
為什么要多一個(gè)這個(gè)間隔層呢,主要是為了實(shí)現(xiàn)跨平臺(tái)。
因?yàn)椴煌钠脚_(tái)的Reactor差異很大。
在Windows平臺(tái),實(shí)現(xiàn)這個(gè)是ACE_WFMO_Reactor
class ACE_Export ACE_WFMO_Reactor : public ACE_Reactor_Impl
3. Event_Handle的管理
ACE_WFMO_Reactor把要管理的Handle都放在 ACE_WFMO_Reactor_Handler_Repository handler_rep_;
這里要注意的是io_handle和event_handle的區(qū)別
io_handle是真正的handle,比如socket_handle, thread_handle
而event_handle是綁定在io_handle上面的事件handle
有代碼為證:
1 int
2 ACE_WFMO_Reactor::register_handler_i (ACE_HANDLE event_handle,
3 ACE_HANDLE io_handle,
4 ACE_Event_Handler *event_handler,
5 ACE_Reactor_Mask new_masks)
6 {
7 // If this is a Winsock 1 system, the underlying event assignment will
8 // not work, so don't try. Winsock 1 must use ACE_Select_Reactor for
9 // reacting to socket activity.
10
11 // Make sure that the <handle> is valid
12 if (io_handle == ACE_INVALID_HANDLE)
13 io_handle = event_handler->get_handle ();
14
15 if (this->handler_rep_.invalid_handle (io_handle))
16 {
17 errno = ERROR_INVALID_HANDLE;
18 return -1;
19 }
20
21 long new_network_events = 0;
22 int delete_event = 0;
23 auto_ptr <ACE_Auto_Event> event;
24
25 // Look up the repository to see if the <event_handler> is already
26 // there.
27 ACE_Reactor_Mask old_masks;
28 int found = this->handler_rep_.modify_network_events_i (io_handle,
29 new_masks,
30 old_masks,
31 new_network_events,
32 event_handle,
33 delete_event,
34 ACE_Reactor::ADD_MASK);
35
36 // Check to see if the user passed us a valid event; If not then we
37 // need to create one
38 if (event_handle == ACE_INVALID_HANDLE)
39 {
40 // Note: don't change this since some C++ compilers have
41 // <auto_ptr>s that don't work properly
42 auto_ptr<ACE_Auto_Event> tmp (new ACE_Auto_Event);
43 event = tmp;
44 event_handle = event->handle ();
45 delete_event = 1;
46 }
47
48 int result = ::WSAEventSelect ((SOCKET) io_handle,
49 event_handle,
50 new_network_events); 可以看到在42行create event,在44復(fù)制到event_handle,最后通過
WSAEventSelect將這個(gè)io_handle和event_handle綁定在一起了
這個(gè)register_handle調(diào)用一般都在Event_Handler的open函數(shù)中,實(shí)現(xiàn)了注冊(cè)到Reactor中去。
4. 等待事件
如何檢測(cè)到要發(fā)生的socket的事件呢?比如有新的client連接,收發(fā)。ACE并不直接調(diào)用select函數(shù)來取得。
ACE調(diào)用
WaitForMultipleObjectsEx來等待事件的發(fā)生。ACE這樣做的好處是不但可以捕捉socket事件,也可以捕捉到其他事件。前面說過了每一個(gè)對(duì)應(yīng)的socket都有一個(gè)event_handle與之對(duì)應(yīng)。
WaitForMultipleObjectsEx會(huì)將發(fā)生事件的socket handle的index返回。這樣ACE_Reactor就可以利用這個(gè)slot來查到io_handle和event_handler( 注意:event_handle和event_handler是不同的)
1 DWORD
2 ACE_WFMO_Reactor::wait_for_multiple_events (int timeout,
3 int alertable)
4 {
5 // Wait for any of handles_ to be active, or until timeout expires.
6 // If <alertable> is enabled allow asynchronous completion of
7 // ReadFile and WriteFile operations.
8
9 return ::WaitForMultipleObjectsEx (this->handler_rep_.max_handlep1 (),
10 this->handler_rep_.handles (),
11 FALSE,
12 timeout,
13 alertable);
14 }
5.分發(fā)事件
根據(jù)WaitForMultiObjectEx返回的slot就可以查詢到event_handler來調(diào)用用戶的處理函數(shù)了
1 int
2 ACE_WFMO_Reactor::complex_dispatch_handler (DWORD slot,
3 ACE_HANDLE event_handle)
4 {
5 // This dispatch is used for I/O entires.
6
7 ACE_WFMO_Reactor_Handler_Repository::Current_Info ¤t_info =
8 this->handler_rep_.current_info ()[slot];
9
10 WSANETWORKEVENTS events;
11 ACE_Reactor_Mask problems = ACE_Event_Handler::NULL_MASK;
12 if (::WSAEnumNetworkEvents ((SOCKET) current_info.io_handle_,
13 event_handle,
14 &events) == SOCKET_ERROR)
15 problems = ACE_Event_Handler::ALL_EVENTS_MASK;
16 else
17 {
18 // Prepare for upcalls. Clear the bits from <events> representing
19 // events the handler is not interested in. If there are any left,
20 // do the upcall(s). upcall will replace events.lNetworkEvents
21 // with bits representing any functions that requested a repeat
22 // callback before checking handles again. In this case, continue
23 // to call back unless the handler is unregistered as a result of
24 // one of the upcalls. The way this is written, the upcalls will
25 // keep being done even if one or more upcalls reported problems.
26 // In practice this may turn out not so good, but let's see. If any
27 // problems, please notify Steve Huston <shuston@riverace.com>
28 // before or after you change this code.
29 events.lNetworkEvents &= current_info.network_events_;
30 while (events.lNetworkEvents != 0)
31 {
32 ACE_Event_Handler *event_handler =
33 current_info.event_handler_;
34
35 int reference_counting_required =
36 event_handler->reference_counting_policy ().value () ==
37 ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
38
39 // Call add_reference() if needed.
40 if (reference_counting_required)
41 {
42 event_handler->add_reference ();
43 }
44
45 // Upcall
46 problems |= this->upcall (current_info.event_handler_,
47 current_info.io_handle_,
48 events);
49
50 // Call remove_reference() if needed.
51 if (reference_counting_required)
52 {
53 event_handler->remove_reference ();
54 }
55
56 if (this->handler_rep_.scheduled_for_deletion (slot))
57 break;
58 }
59 }
60
61 if (problems != ACE_Event_Handler::NULL_MASK
62 && !this->handler_rep_.scheduled_for_deletion (slot) )
63 this->handler_rep_.unbind (event_handle, problems);
64
65 return 0;
66 }
這里值得注意的是ACE通過調(diào)用WSAEnumNetworkEvents來重置event_handle。
講的比較概要,更具體的細(xì)節(jié)請(qǐng)自己閱讀源碼。
關(guān)于ACE_Reactor的用法請(qǐng)參見前一篇我的示例。