pingpong.cpp

来自「ACE自适配通信环境(ADAPTIVE Communication Enviro」· C++ 代码 · 共 309 行

CPP
309
字号
// pingpong.cpp,v 4.27 2005/12/30 11:39:13 jwillemsen Exp/* Simple program that illustrates many features of the ACE_Reactor:   1. I/O event demultiplexing   2. Signal-based demultiplexing   3. Timer-based demultiplexing   To test this program, compile it and then execute it as follows:   % ./pingpong hello   You should see lots of the following output:   writing <4> [7860]   writing <4> [7860]   writing <4> [7860]   writing <4> [7860]   reading <5> (7860) [1] = hello   writing <4> [7860]   writing <5> [7861]   reading <4> (7861) [2] = hello   reading <5> (7860) [2] = hello   writing <4> [7860]   writing <5> [7861]   reading <4> (7861) [3] = hello   reading <5> (7860) [3] = hello   After 10 seconds you'll see the following:   ./pingpong: shutting down tester (pid = 7861)   ./pingpong: shutting down tester (pid = 7860)   and the program will stop.  If you'd like to   stop it earlier, just hit the control-C sequence   and you'll see the same messages. */#include "ace/Reactor.h"#include "ace/Pipe.h"#include "ace/Log_Msg.h"#include "ace/ACE.h"#include "ace/Test_and_Set.h"#include "ace/OS_NS_string.h"#include "ace/Null_Mutex.h"#include "ace/OS_NS_unistd.h"#if defined (ACE_WIN32) || defined (CHORUS)#  include "ace/Barrier.h"#  include "ace/Thread.h"#endif#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)template class ACE_Test_and_Set<ACE_Null_Mutex, sig_atomic_t>;#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)#pragma instantiate ACE_Test_and_Set<ACE_Null_Mutex, sig_atomic_t>#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ACE_RCSID(Misc, pingpong, "pingpong.cpp,v 4.27 2005/12/30 11:39:13 jwillemsen Exp")class Ping_Pong : public ACE_Test_and_Set<ACE_Null_Mutex, sig_atomic_t>{public:  Ping_Pong (char b[], ACE_HANDLE f);  virtual ACE_HANDLE get_handle (void) const;  virtual int handle_input (ACE_HANDLE);  virtual int handle_output (ACE_HANDLE);  virtual int handle_timeout (const ACE_Time_Value &,                              const void *);  virtual int handle_close (ACE_HANDLE handle,                            ACE_Reactor_Mask close_mask);private:  char buf_[BUFSIZ];  // Buffer to send.  size_t buflen_;  // Length of the buffer to send.  int pid_;  // Process ID.  ACE_HANDLE handle_;  // Open handle.};Ping_Pong::Ping_Pong (char b[], ACE_HANDLE f)  : buflen_ (ACE_OS::strlen (b) + 1 + (2 * sizeof (int))),    pid_ (ACE_OS::getpid ()),    handle_ (f){  *((int *) this->buf_) = (int) this->pid_;  *((int *) (this->buf_ + sizeof (int))) = 0;  ACE_OS::strcpy (this->buf_ + (2 * sizeof (int)), b);  this->buf_[this->buflen_ - 1] = '\n';  this->buf_[this->buflen_] = '\0';}ACE_HANDLEPing_Pong::get_handle (void) const{  return this->handle_;}intPing_Pong::handle_close (ACE_HANDLE,                         ACE_Reactor_Mask){  delete this; // Cleanup when we're removed from the reactor.  return 0;}intPing_Pong::handle_input (ACE_HANDLE){#if defined (ACE_HAS_STREAM_PIPES)  // We can rely on record-oriented reads...  ssize_t n = ACE::recv (this->handle_, this->buf_, this->buflen_);  if (n != (ssize_t) this->buflen_)    ACE_ERROR_RETURN ((LM_ERROR,                       ACE_TEXT ("(%P|%t) reading [%d] %p\n"),                       handle_,                       ACE_TEXT ("read")),                      -1);  ACE_DEBUG ((LM_DEBUG,              ACE_TEXT ("(%P|%t) reading <%d> (%d) [%d] = %C\n"),              this->handle_,              *(int *) this->buf_,              *(int *) (this->buf_ + sizeof (int)),              this->buf_ + (2 * sizeof (int))));#else  ssize_t n = ACE::recv (this->handle_,                         this->buf_,                         this->buflen_);  if (n == -1)    ACE_ERROR_RETURN ((LM_ERROR,                       ACE_TEXT ("[%d] %p\n"),                       handle_,                       ACE_TEXT ("read")),                      -1);  n -= (2 * sizeof (int));  char *buf = this->buf_ + (2 * sizeof (int));  ACE_DEBUG ((LM_DEBUG,              ACE_TEXT ("(%P|%t) reading <%d> = %*C\n"),              this->handle_,              n,              buf));#endif /* ACE_HAS_STREAM_PIPES */  return 0;}intPing_Pong::handle_output (ACE_HANDLE){#if defined (ACE_HAS_STREAM_PIPES)  // We can rely on record-oriented reads...  (*(int *) (this->buf_)) = this->pid_;  (*(int *) (this->buf_ + sizeof (int)))++;  if (ACE::send (this->handle_,                 this->buf_,                 this->buflen_) == -1)    return -1;  else    {      ACE_DEBUG ((LM_DEBUG,                  ACE_TEXT ("(%P|%t) writing <%d> [%d]\n"),                  this->handle_,                  this->pid_));      return 0;    }#else  if (ACE::send (this->handle_,                 this->buf_,                 this->buflen_) == -1)    return -1;  else    {      ACE_DEBUG ((LM_DEBUG,                  ACE_TEXT ("(%P|%t) writing <%d>\n"),                  this->handle_));      return 0;    }#endif /* ACE_HAS_STREAM_PIPES */}intPing_Pong::handle_timeout (const ACE_Time_Value &,                           const void *){  this->set (1);  return 0;}// Contains the string to "pingpong" back and forth...static ACE_TCHAR *string_name;// Wait for 10 seconds and then shut down.static const ACE_Time_Value SHUTDOWN_TIME (10);static voidrun_svc (ACE_HANDLE handle){  Ping_Pong *callback = 0;  ACE_NEW (callback,           Ping_Pong (ACE_TEXT_ALWAYS_CHAR (string_name),                      handle));  ACE_Reactor reactor;  // Register the callback object for the various I/O, signal, and  // timer-based events.  if (reactor.register_handler (callback,                                ACE_Event_Handler::READ_MASK                                | ACE_Event_Handler::WRITE_MASK) == -1#if !defined (CHORUS)      || reactor.register_handler (SIGINT,                                   callback) == -1#endif /* CHORUS */      || reactor.schedule_timer (callback,                                 0,                                 SHUTDOWN_TIME) == -1)    {      ACE_ERROR ((LM_ERROR,                  ACE_TEXT ("%p\n"),                  ACE_TEXT ("reactor")));      ACE_OS::exit (1);    }  // Main event loop (one per process).  while (callback->is_set () == 0)    if (reactor.handle_events () == -1)      ACE_ERROR ((LM_ERROR,                  ACE_TEXT ("%p\n"),                  ACE_TEXT ("handle_events")));}#if defined (ACE_WIN32) || defined (CHORUS)static ACE_Barrier barrier (3);static void *worker (void *arg){  ACE_HANDLE handle = (ACE_HANDLE) arg;  run_svc (handle);  // Wait for the threads to exit.  barrier.wait ();  ACE_DEBUG ((LM_DEBUG,              ACE_TEXT ("(%P|%t) %n: shutting down tester\n")));  return 0;}#endif /* ACE_WIN32 */intACE_TMAIN (int argc, ACE_TCHAR *argv[]){  if (argc != 2)    ACE_ERROR_RETURN ((LM_ERROR,                       ACE_TEXT ("usage: pingpong <string>\n")),                       -1);  ACE_LOG_MSG->open (argv[0]);  string_name = argv[1];  ACE_HANDLE handles[2];  // Create a pipe and initialize the handles.  ACE_Pipe pipe (handles);#if defined (ACE_WIN32) || defined (CHORUS)  if (ACE_Thread::spawn (ACE_THR_FUNC (worker),                         (void *) handles[0],                         THR_DETACHED) == -1      || ACE_Thread::spawn (ACE_THR_FUNC (worker),                            (void *) handles[1],                            THR_DETACHED) == -1)      ACE_ERROR ((LM_ERROR,                  ACE_TEXT ("%p\n%a"),                  ACE_TEXT ("spawn"),                  1));  barrier.wait ();#else  pid_t pid = ACE_OS::fork (argv[0]);  if (pid == -1)    ACE_ERROR ((LM_ERROR,                ACE_TEXT ("%p\n%a"),                ACE_TEXT ("fork"),                1));  run_svc (handles[pid == 0]);  ACE_DEBUG ((LM_DEBUG,              ACE_TEXT ("(%P|%t) %n: shutting down tester\n")));#endif /* ACE_WIN32 */  if (pipe.close () == -1)    ACE_ERROR ((LM_ERROR,                ACE_TEXT ("%p\n"),                ACE_TEXT ("close")));  return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?