在 ACE 提供的 Proactor_Test 示例中,整篇代码看不出 Acceptor 和 Connector 是如何与创建的 Proactor 实例关联的,深入ACE源码,顺藤摸瓜,发现这些关联是在ACE内部建立起来的。
Proactor_Test 示例代码在 \ACE-6.0.0\ACE_wrappers\tests 目录下。
Proactor_Test.cpp 文件(文件太长,有删减):
// $Id: Proactor_Test.cpp 91673 2010-09-08 18:49:47Z johnnyw $ // ============================================================================ /** * @file Proactor_Test.cpp * * $Id: Proactor_Test.cpp 91673 2010-09-08 18:49:47Z johnnyw $ * * This program illustrates how the ACE_Proactor can be used to * implement an application that does various asynchronous * operations. * * @author Alexander Libman <[email protected]> */ // ============================================================================ int MyTask::create_proactor (ProactorType type_proactor, size_t max_op) { ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, monitor, this->lock_, -1); ACE_ASSERT (this->proactor_ == 0); #if defined (ACE_WIN32) ACE_UNUSED_ARG (type_proactor); ACE_UNUSED_ARG (max_op); ACE_WIN32_Proactor *proactor_impl = 0; ACE_NEW_RETURN (proactor_impl, ACE_WIN32_Proactor, -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT("(%t) Create Proactor Type = WIN32\n"))); #elif defined (ACE_HAS_AIO_CALLS) ACE_POSIX_Proactor * proactor_impl = 0; switch (type_proactor) { case AIOCB: ACE_NEW_RETURN (proactor_impl, ACE_POSIX_AIOCB_Proactor (max_op), -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Create Proactor Type = AIOCB\n"))); break; #if defined(ACE_HAS_POSIX_REALTIME_SIGNALS) case SIG: ACE_NEW_RETURN (proactor_impl, ACE_POSIX_SIG_Proactor (max_op), -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Create Proactor Type = SIG\n"))); break; #endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */ # if defined (sun) case SUN: ACE_NEW_RETURN (proactor_impl, ACE_SUN_Proactor (max_op), -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT("(%t) Create Proactor Type = SUN\n"))); break; # endif /* sun */ # if !defined(ACE_HAS_BROKEN_SIGEVENT_STRUCT) case CB: ACE_NEW_RETURN (proactor_impl, ACE_POSIX_CB_Proactor (max_op), -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Create Proactor Type = CB\n"))); break; # endif /* !ACE_HAS_BROKEN_SIGEVENT_STRUCT */ default: ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Create Proactor Type = DEFAULT\n"))); break; } #endif /* ACE_WIN32 */ // always delete implementation 1 , not !(proactor_impl == 0) ACE_NEW_RETURN (this->proactor_, ACE_Proactor (proactor_impl, 1 ), -1); // Set new singleton and delete it in close_singleton() ACE_Proactor::instance (this->proactor_, 1); return 0; } int MyTask::delete_proactor (void) { ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, monitor, this->lock_, -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Delete Proactor\n"))); ACE_Proactor::close_singleton (); this->proactor_ = 0; return 0; } int MyTask::start (int num_threads, ProactorType type_proactor, size_t max_op) { if (this->create_proactor (type_proactor, max_op) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p.\n"), ACE_TEXT ("unable to create proactor")), -1); if (this->activate (THR_NEW_LWP, num_threads) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p.\n"), ACE_TEXT ("unable to activate thread pool")), -1); for (; num_threads > 0; num_threads--) { sem_.acquire (); } return 0; } int MyTask::stop () { if (this->proactor_ != 0) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Calling End Proactor event loop\n"))); this->proactor_->proactor_end_event_loop (); } if (this->wait () == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p.\n"), ACE_TEXT ("unable to stop thread pool"))); return 0; } int MyTask::svc (void) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) MyTask started\n"))); disable_signal (ACE_SIGRTMIN, ACE_SIGRTMAX); disable_signal (SIGPIPE, SIGPIPE); // signal that we are ready sem_.release (1); ACE_Proactor::run_event_loop (); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) MyTask finished\n"))); return 0; } class Acceptor : public ACE_Asynch_Acceptor<Server> { public: Acceptor (TestData *tester); virtual ~Acceptor (void); // Virtual from ACE_Asynch_Acceptor Server *make_handler (void); private: TestData *tester_; }; // ************************************************************* Acceptor::Acceptor (TestData *tester) : tester_ (tester) { } Acceptor::~Acceptor (void) { this->cancel (); } Server * Acceptor::make_handler (void) { return this->tester_->server_up (); } // ******************************************* // Connector // ******************************************* class Connector : public ACE_Asynch_Connector<Client> { public: Connector (TestData *tester); virtual ~Connector (void); int start (const ACE_INET_Addr &addr, int num); // Virtual from ACE_Asynch_Connector Client *make_handler (void); private: TestData *tester_; }; // ************************************************************* Connector::Connector (TestData *tester) : tester_ (tester) { } Connector::~Connector (void) { this->cancel (); } Client * Connector::make_handler (void) { return this->tester_->client_up (); } int Connector::start (const ACE_INET_Addr& addr, int num) { if (num > MAX_CLIENTS) num = MAX_CLIENTS; if (num < 0) num = 1; int rc = 0; // int open ( int pass_addresses = 0, // ACE_Proactor *proactor = 0, // int validate_new_connection = 0 ); if (this->open (1, 0, 1) != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("Connector::open failed"))); return rc; } for (; rc < num; rc++) { if (this->connect (addr) != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("Connector::connect failed"))); break; } } return rc; } int run_main (int argc, ACE_TCHAR *argv[]) { ACE_START_TEST (ACE_TEXT ("Proactor_Test")); if (::parse_args (argc, argv) == -1) return -1; disable_signal (ACE_SIGRTMIN, ACE_SIGRTMAX); disable_signal (SIGPIPE, SIGPIPE); MyTask task1; TestData test; if (task1.start (threads, proactor_type, max_aio_operations) == 0) { Acceptor acceptor (&test); Connector connector (&test); ACE_INET_Addr addr (port); int rc = 0; if (both != 0 || host == 0) // Acceptor { // Simplify, initial read with zero size if (acceptor.open (addr, 0, 1) == 0) rc = 1; } if (both != 0 || host != 0) { if (host == 0) host = ACE_LOCALHOST; if (addr.set (port, host, 1, addr.get_type ()) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), host)); else rc += connector.start (addr, clients); } // Wait a few seconds to let things get going, then poll til // all sessions are done. Note that when we exit this scope, the // Acceptor and Connector will be destroyed, which should prevent // further connections and also test how well destroyed handlers // are handled. ACE_OS::sleep (3); } ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Sleeping til sessions run down.\n"))); while (!test.testing_done ()) ACE_OS::sleep (1); test.stop_all (); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Stop Thread Pool Task\n"))); task1.stop (); ACE_END_TEST; return 0; } #else int run_main (int, ACE_TCHAR *[]) { ACE_START_TEST (ACE_TEXT ("Proactor_Test")); ACE_DEBUG ((LM_INFO, ACE_TEXT ("Threads or Asynchronous IO is unsupported.\n") ACE_TEXT ("Proactor_Test will not be run."))); ACE_END_TEST; return 0; } #endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
分析如下:
1. ACE_Proactor::instance (this->proactor_, 1); // 把创建的Proactor实例传入ACE_Proactor类中保存。
2.
int run_main (int argc, ACE_TCHAR *argv[])
{
...
if (both != 0 || host == 0) // Acceptor
{
// Simplify, initial read with zero size
// 调用Acceptor的open函数,看似与创建的proactor实例没有一点关系,但深入ACE代码内部就知道,Acceptor和Proactor是在内部关联了。
if (acceptor.open (addr, 0, 1) == 0)
rc = 1;
}
...
}
3.
int Connector::start (const ACE_INET_Addr& addr, int num)
{
...
// 与Acceptor类似,调用Connector的open函数,看似与创建的proactor实例没有一点关系,但深入ACE代码内部就知道,Connector和Proactor是在内部关联了。
if (this->open (1, 0, 1) != 0)
{
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("(%t) %p\n"),
ACE_TEXT ("Connector::open failed")));
return rc;
}
...
}