在 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 <alibman@baltimore.com>
*/
// ============================================================================
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;
}
...
}