Linux Proactor测试程序

    虽然linux 2.6内核将对aio的支持集成到内核中,但linux 2.6内核aio对socket的支持却不是真正的异步的。对socket的异步IO请求在内核中自动被转换成同步的调用。如果先对一个socket提交一个读操作,然后提交一个写操作,那么写操作只有在读操作完整之后才能执行。这对Proactor在Linux下的实际应用有严重的影响。ace自带一个测试程序$ACE_ROOT/example/Reactor/Proactor/test_proactor2.cpp。但该测试程序的测试成功基本上只意味着Proactor能在Linux下编译并运行。本文对该测试用来进行加强,如果本测试程序能测试通过,那就意味着Proactor在Linux能提供实际的应用支持。

编译命令如下:

g++ -o test_proactor21 test_proactor21.cpp -nostartfiles  -I/usr/local/include -L/usr/local/lib -lACE -lpthread

代码如下:

// test_proactor2.cpp,v 1.8 2003/11/10 01:48:03 dhinton Exp

// ============================================================================
//
// = LIBRARY
//    examples
//
// = FILENAME
//    test_proactor2.cpp
//
// = DESCRIPTION
//    Alexander Libman <Alibman@baltimore.com> modified
//    <test_proactor> and made this test. Instead of writing received
//    data to the file, the receiver sends them back to the
//    sender,i.e. ACE_Asynch_Write_File wf_  has been changed to
//    ACE_Asynch_Write_Stream wf_.
//
// = AUTHOR
//    Irfan Pyarali <irfan@cs.wustl.edu> and Alexander Libman
//    <Alibman@baltimore.com>.
// ============================================================================

#include "ace/Signal.h"

#include "ace/Service_Config.h"
#include "ace/Proactor.h"
#include "ace/POSIX_CB_Proactor.h"
#include "ace/Asynch_IO.h"
#include "ace/Asynch_IO_Impl.h"
#include "ace/Asynch_Acceptor.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Connector.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Stream.h"
#include "ace/Message_Block.h"
#include "ace/Get_Opt.h"

#ifndef WIN32
#include <netinet/tcp.h>
#endif

// FUZZ: disable check_for_streams_include
#include "ace/streams.h"

#include "ace/Task.h"
#include "ace/OS_main.h"

ACE_RCSID(Proactor, test_proactor2, "test_proactor2.cpp,v 1.27 2000/03/07 17:15:56 schmidt Exp")

#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
  // This only works on Win32 platforms and on Unix platforms supporting
  // POSIX aio calls.

#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)

#include "ace/WIN32_Proactor.h"

#elif defined (ACE_HAS_AIO_CALLS)

#include "ace/POSIX_Proactor.h"

#endif

  //  Some debug helper functions
  int DisableSignal ( int SigNum );
int PrintSigMask ();

#define  COUT(X)  cout << X ; cout.flush ();

// Host that we're connecting to.
static ACE_TCHAR *host = 0;

// duplex mode: ==0 half-duplex
//              !=0 full duplex
static int duplex = 0 ;

static int init_method = 0;

// number threads in the Proactor thread pool
static int nThreads = 1;

// Port that we're receiving connections on.
static u_short port = ACE_DEFAULT_SERVER_PORT;

// Size of each initial asynchronous <read> operation.
static int initial_read_size = BUFSIZ;

static int counter1 = 0 ;

#define MyMutex ACE_Recursive_Thread_Mutex
//#define MyMutex ACE_Thread_Mutex
//#define MyMutex ACE_Null_Mutex

//--------------------------------------------------------------------------
// MyTask plays role for Proactor threads pool
//--------------------------------------------------------------------------
class MyTask: public ACE_Task<ACE_MT_SYNCH>
{

public:

  int svc (void) ;
};


int MyTask::svc (void )
{
  ACE_DEBUG ((LM_DEBUG, "(%t) MyTask started/n"));

  while ( ACE_Proactor::event_loop_done () == 0 )
    {
      ACE_Proactor::run_event_loop ();
    }

  ACE_DEBUG ((LM_DEBUG, "(%t) MyTask finished/n"));
  return 0 ;
}

//-----------------------------------------------------------
//  Receiver
//-----------------------------------------------------------
class Receiver : public ACE_Service_Handler
{
public:

  Receiver (void);
  ~Receiver (void);

  virtual void open (ACE_HANDLE handle,
                     ACE_Message_Block &message_block);
  // This is called after the new connection has been accepted.

protected:
  // These methods are called by the framework

  virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result
                                   &result);
  // This is called when asynchronous <read> operation from the socket
  // complete.

  virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result
                                    &result);
  // This is called when an asynchronous <write> to the file
  // completes.

private:
  int  initiate_read_stream  (void);
  int  initiate_write_stream (ACE_Message_Block & mb, int nBytes );
  bool check_destroy () ;

  ACE_Asynch_Read_Stream rs_;
  ACE_Asynch_Write_Stream ws_;
  ACE_HANDLE handle_;
  MyMutex m_Mtx ;
  long    nIOCount ;
  static long nSessions ;
};


long Receiver::nSessions = 0 ;

Receiver::Receiver (void)
  : handle_ (ACE_INVALID_HANDLE),
    nIOCount ( 0 )
{
  ACE_Guard<MyMutex> locker (m_Mtx) ;
  nSessions ++ ;
  ACE_DEBUG ((LM_DEBUG, "Receiver Ctor nSessions=%d/n", nSessions ));
}

Receiver::~Receiver (void)
{
  ACE_Guard<MyMutex> locker (m_Mtx) ;
  nSessions -- ;
  ACE_OS::closesocket (this->handle_);
  ACE_DEBUG ((LM_DEBUG, "~Receiver Dtor nSessions=%d/n", nSessions ));
}

//---------------------------------------------------------------------
//  return true if we alive, false  we commited suicide
//
//---------------------------------------------------------------------
bool Receiver::check_destroy ()
{
  {
    ACE_Guard<MyMutex> locker (m_Mtx) ;

    if ( nIOCount > 0 )
      {
        return true ;
      }
  }

  delete this ;
  return false ;
}


void Receiver::open (ACE_HANDLE handle,
                     ACE_Message_Block &message_block)
{
  ACE_UNUSED_ARG (message_block);

  ACE_DEBUG ((LM_DEBUG,
              "%N:%l:Receiver::open called/n"));


  this->handle_ = handle;

  int nodelay = 1;
  ACE_SOCK_Stream option_setter (handle);
  if (-1 == option_setter.set_option (ACE_IPPROTO_TCP,TCP_NODELAY,&nodelay,sizeof (nodelay)))
   ACE_ERROR ((LM_ERROR, "%p/n", "set_option"));

  if (this->ws_.open (*this, this->handle_ ) == -1)
    {
      ACE_ERROR ((LM_ERROR,
                  "%p/n",
                  "ACE_Asynch_Write_Stream::open"));

    }
  else if (this->rs_.open (*this, this->handle_) == -1)
    {
      ACE_ERROR ((LM_ERROR,
                  "%p/n",
                  "ACE_Asynch_Read_Stream::open"));
    }
  else
    {
      initiate_read_stream ();
    }


  check_destroy ();
}

int Receiver::initiate_read_stream (void)
{
  ACE_Guard<MyMutex> locker (m_Mtx) ;

  // Create a new <Message_Block>.  Note that this message block will
  // be used both to <read> data asynchronously from the socket and to
  // <write> data asynchronously to the file.
  ACE_DEBUG ((LM_DEBUG,
              "initiate_read_stream called/n"));


  ACE_Message_Block *mb = 0;
  ACE_NEW_RETURN (mb,
                  ACE_Message_Block (BUFSIZ + 1),
                  -1);

  // Inititiate read
  if (this->rs_.read (*mb, mb->size ()- 1) == -1)
    {
      mb->release () ;
      ACE_ERROR_RETURN ((LM_ERROR,
                         "%p/n",
                         "ACE_Asynch_Read_Stream::read"),
                        -1);
    }

  nIOCount++ ;
  return 0;
}

int Receiver::initiate_write_stream (ACE_Message_Block & mb, int nBytes )
{
  ACE_Guard<MyMutex> locker (m_Mtx) ;
  if (this->ws_.write (mb , nBytes ) == -1)
    {
      mb.release ();
      ACE_ERROR_RETURN((LM_ERROR,
                        "%p/n",
                        "ACE_Asynch_Write_File::write"),
                       -1);
    }

  nIOCount++ ;
  return 0;
}

void
Receiver::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
{
  ACE_DEBUG ((LM_DEBUG,
              "handle_read_stream called/n"));

  // Reset pointers.
  result.message_block ().rd_ptr ()[result.bytes_transferred ()] =
    '/0';

  ACE_DEBUG ((LM_DEBUG, "********************/n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "bytes_to_read", result.bytes_to_read
              ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "handle", result.handle ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "bytes_transfered",
              result.bytes_transferred ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "act", (u_long) result.act ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "success", result.success ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "completion_key", (u_long)
              result.completion_key ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "error", result.error ()));
  ACE_DEBUG ((LM_DEBUG, "********************/n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %s/n", "message_block",
              result.message_block ().rd_ptr ()));

  if ( result.success () && result.bytes_transferred () != 0)
    {
      // Successful read: write the data to the file asynchronously.
      // Note how we reuse the <ACE_Message_Block> for the writing.
      // Therefore, we do not delete this buffer because it is handled
      // in <handle_write_stream>.

      if(this->initiate_write_stream (result.message_block (),

                                      result.bytes_transferred () ) == 0 )
        {
          if ( duplex != 0 )
            {
              // Initiate new read from the stream.
              this->initiate_read_stream () ;
            }
        }
    }
  else
    {
      result.message_block ().release ();
      ACE_DEBUG ((LM_DEBUG,  "Receiver completed/n"));
    }

  {
    ACE_Guard<MyMutex> locker (m_Mtx) ;
    nIOCount-- ;
  }
  check_destroy () ;
}

void
Receiver::handle_write_stream (const ACE_Asynch_Write_Stream::Result
                               &result)
{
  ACE_DEBUG ((LM_DEBUG, "handle_write_stream called/n"));

  ACE_DEBUG ((LM_DEBUG, "********************/n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "bytes_to_write",
              result.bytes_to_write ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "handle", result.handle ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "bytes_transfered",
              result.bytes_transferred ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "act", (u_long) result.act ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "success", result.success ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "completion_key", (u_long)
              result.completion_key ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "error", result.error ()));
  ACE_DEBUG ((LM_DEBUG, "********************/n"));

  result.message_block ().release ();

  if (result.success ())
    {
      // This code is not robust enough to deal with short file writes
      // (which hardly ever happen) ;-)
      //ACE_ASSERT (result.bytes_to_write () == result.bytes_transferred ());

      if ( duplex == 0 )
        {
          initiate_read_stream () ;
        }
    }

  {
    ACE_Guard<MyMutex> locker (m_Mtx) ;
    nIOCount-- ;
  }
  check_destroy () ;
}

//-------------------------------------------------------------------------
// Sender:  sends indefinetely welcome message
//  and  recieves it back
//------------------------------------------------------------------------
class Sender : public ACE_Handler
{
public:
  Sender (void);
  ~Sender (void);
  int open (const ACE_TCHAR *host, u_short port);
  void close ();
  ACE_HANDLE handle (void) const;
  void handle (ACE_HANDLE);
 
  int initiate_write_stream (void);

protected:
// These methods are called by the freamwork

virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result
&result);
// This is called when asynchronous reads from the socket complete

virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result
&result);
// This is called when asynchronous writes from the socket complete

 
private:

int initiate_read_stream (void);


ACE_SOCK_Stream stream_;
// Network I/O handle

ACE_Asynch_Write_Stream ws_;
// ws (write stream): for writing to the socket

ACE_Asynch_Read_Stream rs_;
// rs (read file): for reading from the socket

ACE_Message_Block welcome_message_;
// Welcome message

MyMutex m_Mtx ;
long    nIOCount ;
};


#define POST_COMPLETION

#if defined(WIN32) || defined(POST_COMPLETION)

class ACE_POSIX_InitWrite_Notification : public ACE_POSIX_Asynch_Result
{
 Sender *m_sender ;
 
public:
  /// Constructor.
  ACE_POSIX_InitWrite_Notification (Sender *sender,
            const ACE_Handler::Proxy_Ptr &handler_proxy,
                               const void *act = 0,
                               ACE_HANDLE event = ACE_INVALID_HANDLE,
                               int priority = 0,
                               int signal_number = ACE_SIGRTMIN):                   
    ACE_POSIX_Asynch_Result(handler_proxy, act, event, (u_long)0, (u_long)0, priority, signal_number),
    m_sender(sender)
  {
  }

  /// Destructor.
  virtual ~ACE_POSIX_InitWrite_Notification (void)
  {
  }
 
  virtual void complete (size_t bytes_transferred,
                         int success,
                         const void *completion_key,
                         u_long error = 0)
  {
   
   ACE_DEBUG((LM_DEBUG,"ACE_POSIX_InitWrite_Notification::complete called/n"));
   m_sender->initiate_write_stream();
  }
};


struct Event
{
 Sender *sender ; 
};

class EventTask: public ACE_Task<ACE_MT_SYNCH>
{

public:

  int svc (void)
  {
    ACE_Message_Block *msg ;
   while(getq(msg) != -1)
 {
  Event *event = (Event *)msg->base();
  //event->sender->initiate_write_stream();

  ACE_DEBUG((LM_DEBUG,"PostEvent::Handle called/n"));
  //m_sender->initiate_write_stream(); 
  
  static int count = 0 ;
  ACE_DEBUG((LM_DEBUG,"Sleep(%d)/n",count++));
  ACE_OS::sleep(1);
  
  ACE_POSIX_InitWrite_Notification *notify = NULL;
  ACE_NEW_RETURN(notify,ACE_POSIX_InitWrite_Notification(event->sender,(dynamic_cast<ACE_Handler *>(event->sender))->proxy()),-1);
  
  ACE_Proactor *proactor = ACE_Proactor::instance();
  ACE_Proactor_Impl * proactor_impl = proactor->implementation();
  notify->post_completion(proactor_impl);

  delete msg ;
 }
  }   

  void enqueue(Sender *sender)
  {
 ACE_Message_Block *msg ;
 ACE_NEW(msg,ACE_Message_Block(sizeof(Event)));
 Event *event = (Event *)msg->base();
 event->sender = sender ;
 putq(msg);
  }

  void close()
  {
 this->msg_queue()->close();
  }
};


EventTask event_task ;

#endif


static char *data = "Welcome to Irfan World! Irfan RULES here !!/n";

Sender::Sender (void)
  :nIOCount ( 0 )
{
  // Moment of inspiration... :-)
  this->welcome_message_.init (data, ACE_OS::strlen (data));
}

Sender::~Sender (void)
{
  close ();
}

void Sender::close ()
{
  this->stream_.close ();
}

ACE_HANDLE Sender::handle (void) const
{
  return this->stream_.get_handle ();
}

void Sender::handle (ACE_HANDLE handle)
{
  this->stream_.set_handle (handle);
}

int Sender::open (const ACE_TCHAR *host, u_short port)
{
  // Initialize stuff
  // Connect to remote host
  ACE_INET_Addr address (port, host);
  ACE_SOCK_Connector connector;

  if (connector.connect (this->stream_,
                         address) == -1)
    {
      ACE_ERROR_RETURN ((LM_ERROR,
                         "%p/n",
                         "ACE_SOCK_Connector::connect"),
                        -1);
    }

 int nodelay = 1;
 ACE_SOCK_Stream option_setter (stream_.get_handle());
 if (-1 == option_setter.set_option (ACE_IPPROTO_TCP,TCP_NODELAY,&nodelay,sizeof (nodelay)))
  ACE_ERROR ((LM_ERROR, "%p/n", "set_option"));

  // Open ACE_Asynch_Write_Stream
  if (this->ws_.open (*this) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p/n",
                       "ACE_Asynch_Write_Stream::open"),
                      -1);

  // Open ACE_Asynch_Read_Stream
  if (this->rs_.open (*this) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p/n",
                       "ACE_Asynch_Read_File::open"),
                      -1);

  // Start an asynchronous transmit file
  if ( this->initiate_write_stream () == -1)
    return -1;

  if ( duplex != 0 )
    {
      // Start an asynchronous read file
      if (this->initiate_read_stream () == -1)
        return -1;
    }

  return 0;
}

int Sender::initiate_write_stream (void)
{
  ACE_Guard<MyMutex> locker (m_Mtx) ;


  welcome_message_.rd_ptr( welcome_message_.base ());
  welcome_message_.wr_ptr( welcome_message_.base ());
  welcome_message_.wr_ptr (ACE_OS::strlen (data));

  if (this->ws_.write (welcome_message_,
                       welcome_message_.length ()
                       ) == -1)
    {
      ACE_ERROR_RETURN((LM_ERROR,
                        "%p/n",
                        "ACE_Asynch_Write_File::write"),
                       -1);
    }

  nIOCount++ ;
  return 0;
}

int Sender::initiate_read_stream (void)
{
  ACE_Guard<MyMutex> locker (m_Mtx) ;

  // Create a new <Message_Block>.  Note that this message block will
  // be used both to <read> data asynchronously from the socket and to
  // <write> data asynchronously to the file.
  ACE_DEBUG ((LM_DEBUG,
              "initiate_read_stream called/n"));


  ACE_Message_Block *mb = 0;
  ACE_NEW_RETURN (mb,
                  ACE_Message_Block (BUFSIZ + 1),
                  -1);

  // Inititiate read
  if (this->rs_.read (*mb, mb->size ()- 1) == -1)
    {
      mb->release () ;
      ACE_ERROR_RETURN ((LM_ERROR,
                         "%p/n",
                         "ACE_Asynch_Read_Stream::read"),
                        -1);
    }

  nIOCount++ ;
  return 0;
}


void Sender::handle_write_stream (const ACE_Asynch_Write_Stream::Result
                                  &result)
{
  ACE_DEBUG ((LM_DEBUG,
              "handle_write_stream called/n"));

  // Reset pointers.
  result.message_block ().rd_ptr (result.message_block ().rd_ptr () -
                                  result.bytes_transferred ());


  ACE_DEBUG ((LM_DEBUG, "********************/n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "bytes_to_write",
              result.bytes_to_write ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "handle", result.handle ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "bytes_transfered",
              result.bytes_transferred ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "act", (u_long) result.act ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "success", result.success ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "completion_key", (u_long)
              result.completion_key ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "error", result.error ()));
  ACE_DEBUG ((LM_DEBUG, "********************/n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %s/n", "message_block",
              result.message_block ().rd_ptr ()));

  // Simplify just for Test
  if (result.success () && result.bytes_transferred () != 0)
    {
      if ( duplex != 0 )  // full duplex, continue write
        {
       
         if(init_method == 0)
         {
          ACE_DEBUG((LM_DEBUG,"(%d)handle_write_stream call initiate_write_stream/n",counter1++));  
          ACE_OS::sleep(1);
          initiate_write_stream () ;
         }
         else if(init_method == 1)
         {
          ACE_DEBUG((LM_DEBUG,"(%d)handle_write_stream use ACE_POSIX_InitWrite_Notification/n",counter1++));  
          ACE_POSIX_InitWrite_Notification *notify = NULL;
    ACE_NEW(notify,ACE_POSIX_InitWrite_Notification(this,(dynamic_cast<ACE_Handler *>(this))->proxy()));
 
    ACE_OS::sleep(1);
     
    ACE_Proactor *proactor = ACE_Proactor::instance();
    ACE_Proactor_Impl * proactor_impl = proactor->implementation();
    notify->post_completion(proactor_impl);
   }
   else
   {
     ACE_DEBUG((LM_DEBUG,"handle_write_stream post_event duplex=1/n"));
           event_task.enqueue(this);
   }
 
        }
      else  // half-duplex   read reply, after read we will start
        // write
        {
          initiate_read_stream () ;
        }
    }

  {
    ACE_Guard<MyMutex> locker (m_Mtx) ;
    nIOCount-- ;
  }
}

void
Sender::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
{
  ACE_DEBUG ((LM_DEBUG,
              "handle_read_stream called/n"));

  // Reset pointers.
  result.message_block ().rd_ptr ()[result.bytes_transferred ()] =
    '/0';

  ACE_DEBUG ((LM_DEBUG, "********************/n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "bytes_to_read", result.bytes_to_read
              ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "handle", result.handle ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "bytes_transfered",
              result.bytes_transferred ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "act", (u_long) result.act ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "success", result.success ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "completion_key", (u_long)
              result.completion_key ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d/n", "error", result.error ()));
  ACE_DEBUG ((LM_DEBUG, "********************/n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %s/n", "message_block",
              result.message_block ().rd_ptr ()));

  result.message_block().release ();

  if ( result.success () && result.bytes_transferred () != 0)
    {
      // Successful read: write the data to the file asynchronously.
      // Note how we reuse the <ACE_Message_Block> for the writing.
      // Therefore, we do not delete this buffer because it is handled
      // in <handle_write_stream>.

      if ( duplex != 0 )  // full duplex, continue read
        {
          initiate_read_stream () ;
        }
      else  // half-duplex  writey, after write we will start read
        {
        
         if(init_method == 0)
         {
          ACE_DEBUG((LM_DEBUG,"(%d)handle_write_stream call initiate_write_stream/n",counter1++));  
          initiate_write_stream () ;
         }
         else if(init_method == 1)
         {
          ACE_DEBUG((LM_DEBUG,"(%d)handle_write_stream use ACE_POSIX_InitWrite_Notification/n",counter1++));  
          ACE_POSIX_InitWrite_Notification *notify = NULL;
    ACE_NEW(notify,ACE_POSIX_InitWrite_Notification(this,(dynamic_cast<ACE_Handler *>(this))->proxy()));
   
    ACE_OS::sleep(1);
 
    ACE_Proactor *proactor = ACE_Proactor::instance();
    ACE_Proactor_Impl * proactor_impl = proactor->implementation();
    notify->post_completion(proactor_impl);
   }
   else
   {
  
    ACE_DEBUG((LM_DEBUG,"handle_write_stream post_event duplex=1/n"));
          event_task.enqueue(this);
   }
        }
    }

  {
    ACE_Guard<MyMutex> locker (m_Mtx) ;
    nIOCount-- ;
  }
}

/


//--------------------------------------------------------------------------

static int
parse_args (int argc, ACE_TCHAR *argv[])
{
  ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("n:p:d:h:m:"));
  int c;

  while ((c = get_opt ()) != EOF)
    switch (c)
      {
      case 'm':
       {
        init_method = ACE_OS::atoi (get_opt.opt_arg ()) ;
       }
       break;
      case 'h':
        host = get_opt.opt_arg ();
        break;
      case 'n':
        nThreads = ACE_OS::atoi (get_opt.opt_arg ()) ;
        break;
      case 'p':
        port = ACE_OS::atoi (get_opt.opt_arg ());
        break;
      case 'd':
        duplex = ACE_OS::atoi (get_opt.opt_arg ());
        break;
      default:
        ACE_ERROR ((LM_ERROR, "%p./n",
                    "usage :/n"
                    "-h <host> for Sender mode/n"
                    "-d <duplex mode 1-on/0-off>/n"
                    "-p <port to listen/connect>/n"
                    "-n <number threads for Proactor pool>/n"
     "-m <method of initiate write stream>/n"
     "   0 - in Proactor thread directory/n"
     "   1 - in Proactor thread indirectory/n"
     "   2 - Event Tash post request to Proactor thread/n"));
        return -1;
      }

  return 0;
}

int main(int argc, char *argv[])
{
  ACE_UNUSED_ARG (initial_read_size);

  if (parse_args (argc, argv) == -1)
    return -1;

#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)

  ACE_WIN32_Proactor *      pImpl = new ACE_WIN32_Proactor;

#elif defined (ACE_HAS_AIO_CALLS)

  //ACE_POSIX_AIOCB_Proactor *  pImpl = new ACE_POSIX_AIOCB_Proactor;
  ACE_POSIX_CB_Proactor *  pImpl = new ACE_POSIX_CB_Proactor;
  //ACE_POSIX_SIG_Proactor *  pImpl = new ACE_POSIX_SIG_Proactor;
#endif

  ACE_Proactor Proactor ( pImpl ,1 );

  ACE_Proactor::instance( & Proactor );


  MyTask  Task1 ;

  if (Task1.activate (THR_NEW_LWP, nThreads ) == -1)
    {
      ACE_ERROR_RETURN ((LM_ERROR, "%p./n", "main"), -1);
    }

   if (event_task.activate (THR_NEW_LWP, 1 ) == -1)
    {
      ACE_ERROR_RETURN ((LM_ERROR, "%p./n", "main"), -1);
    }

  Sender sender;
  ACE_Asynch_Acceptor<Receiver> acceptor;

  int Rc = -1 ;

  if ( host == NULL ) // Acceptor
    {
      // Simplify , initial read with  zero size
      Rc = acceptor.open (ACE_INET_Addr (port),0,1);

    }
  else
    {
      Rc = sender.open (host, port);
    }

  if ( Rc == 0 )
    {
      char c ;
      cout << "Press any key to stop and exit=>/n" << flush ;
      cin.clear ();
      cin >> c ;
    }

  ACE_Proactor::end_event_loop () ;

  if ( host != NULL ) // we are sender
    {
      sender.close () ; // disconnect to get reciever error !!!
    }


  event_task.close();

  ACE_Thread_Manager * pTM = ACE_Thread_Manager::instance();

  pTM->wait_task ( & event_task ) ;
  pTM->wait_task ( & Task1 ) ;

  ACE_Proactor::instance( ( ACE_Proactor* )NULL );

  return 0;
}
//--------------------------------------------------------------------
//
//--------------------------------------------------------------------
int DisableSignal ( int SigNum )
{

#ifndef ACE_WIN32
  sigset_t signal_set;
  if ( sigemptyset (&signal_set) == - 1 )
    {
      ACE_ERROR ((LM_ERROR,
                  "Error:(%P | %t):%p/n",
                  "sigemptyset failed"));
    }

  sigaddset (&signal_set, SigNum);

  //  Put the <signal_set>.
  if (ACE_OS::pthread_sigmask (SIG_BLOCK, &signal_set, 0) != 0)
    {
      ACE_ERROR ((LM_ERROR,
                  "Error:(%P | %t):%p/n",
                  "pthread_sigmask failed"));
    }
#else
  ACE_UNUSED_ARG(SigNum);
#endif

  return  1;
}
//--------------------------------------------------------------------
// Get the <signal_set> back from the OS.
//--------------------------------------------------------------------

int PrintSigMask ()
{
#ifndef ACE_WIN32

  sigset_t  mask ;
  int member = 0;

  COUT ( "/n=============Signal Mask==========" )

    if (ACE_OS::pthread_sigmask (SIG_SETMASK, 0, & mask ) != 0)
      {
        ACE_ERROR ((LM_ERROR,
                    "Error:(%P | %t):%p/n",
                    "ACE_OS::pthread_sigmask failed"));
      }
    else  for (int i = 1 ; i < 1000; i++)
      {
        member = sigismember (&mask,i);

        COUT ( "/nSig " )
          COUT ( i )
          COUT ( " is " )
          COUT (member )

          if (member == -1)
            {
              break ;
            }
      }
#endif
  return 0;
}


#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class ACE_Asynch_Acceptor<Receiver>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate ACE_Asynch_Acceptor<Receiver>
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */

#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值