diff options
author | alex <alex@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-02-16 06:38:49 +0000 |
---|---|---|
committer | alex <alex@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-02-16 06:38:49 +0000 |
commit | 7211c1e2fcda52e3bce16a29f05cc8f94fbab56c (patch) | |
tree | 6103a5605b624fe5306a57d8c8db1e4888734bc1 /ace | |
parent | c3ea40ae39854fb98b82ab6c9e415010ff09b26d (diff) | |
download | ATCD-7211c1e2fcda52e3bce16a29f05cc8f94fbab56c.tar.gz |
*** empty log message ***
Diffstat (limited to 'ace')
-rw-r--r-- | ace/Asynch_IO_Impl.cpp | 14 | ||||
-rw-r--r-- | ace/Asynch_IO_Impl.h | 464 | ||||
-rw-r--r-- | ace/Asynch_IO_Impl.i | 87 | ||||
-rw-r--r-- | ace/POSIX_Asynch_IO.h | 1085 | ||||
-rw-r--r-- | ace/POSIX_Proactor.cpp | 1138 | ||||
-rw-r--r-- | ace/WIN32_Proactor.i | 2 |
6 files changed, 2790 insertions, 0 deletions
diff --git a/ace/Asynch_IO_Impl.cpp b/ace/Asynch_IO_Impl.cpp new file mode 100644 index 00000000000..9baab6f5e04 --- /dev/null +++ b/ace/Asynch_IO_Impl.cpp @@ -0,0 +1,14 @@ +// $Id$ +#define ACE_BUILD_DLL +#include "ace/OS.h" +#include "ace/Asynch_IO_Impl.h" + +#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)) +// This only works on Win32 platforms and on Unix platforms supporting +// aio calls. + +#if !defined (__ACE_INLINE__) +#include "ace/Asynch_IO_Impl.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_WIN32 || ACE_HAS_WINCE */ diff --git a/ace/Asynch_IO_Impl.h b/ace/Asynch_IO_Impl.h new file mode 100644 index 00000000000..21b8a9e245c --- /dev/null +++ b/ace/Asynch_IO_Impl.h @@ -0,0 +1,464 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// +// ace +// +// = FILENAME +// +// Asynch_IO_Impl.h +// +// = DESCRIPTION +// +// This class contains asbtract base classes for all the concrete +// implementation classes for the various asynchronous operations +// that are used with the Praoctor. +// +// = AUTHOR +// +// Irfan Pyarali (irfan@cs.wustl.edu), +// Tim Harrison (harrison@cs.wustl.edu) and +// Alexander Babu Arulanthu <alex@cs.wustl.edu> +// +// ============================================================================ + +#if !defined (ACE_ASYNCH_IO_IMPL_H) +#define ACE_ASYNCH_IO_IMPL_H + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)) +// This only works on Win32 platforms and on Unix platforms supporting +// aio calls. + +#include "ace/Asynch_IO.h" + +class ACE_Export ACE_Asynch_Result_Impl +{ + // = TITLE + // + // Abstract base class for the all the classes that provide + // concrete implementations for ACE_Asynch_Result. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Result_Impl (void) {} + + virtual u_long bytes_transferred (void) const = 0; + // Number of bytes transferred by the operation. + + virtual const void *act (void) const = 0; + // ACT associated with the operation. + + virtual int success (void) const = 0; + // Did the operation succeed? + + virtual const void *completion_key (void) const = 0; + // This ACT is not the same as the ACT associated with the + // asynchronous operation. + + virtual u_long error (void) const = 0; + // Error value if the operation fail. + + virtual ACE_HANDLE event (void) const = 0; + // Event associated with the OVERLAPPED structure. + + virtual u_long offset (void) const = 0; + virtual u_long offset_high (void) const = 0; + // This really make sense only when doing file I/O. + + virtual int priority (void) const = 0; + // Priority of the operation. + + // protected: + // + // These two should really be protected. But sometimes it + // simplifies code to be able to "fake" a result. Use carefully. + virtual void complete (u_long bytes_transferred, + int success, + const void *completion_key, + u_long error = 0) = 0; + // This is called when the asynchronous operation completes. + +protected: + ACE_Asynch_Result_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Operation_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Operation. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Operation_Impl () {} + + virtual int open (ACE_Handler &handler, + ACE_HANDLE handle, + const void *completion_key, + ACE_Proactor *proactor) = 0; + // Initializes the factory with information which will be used with + // each asynchronous call. If (<handle> == ACE_INVALID_HANDLE), + // <ACE_Handler::handle> will be called on the <handler> to get the + // correct handle. + + virtual int cancel (void) = 0; + // This cancels all pending accepts operations that were issued by + // the calling thread. The function does not cancel asynchronous + // operations issued by other threads. + + // = Access methods. + + virtual ACE_Proactor* proactor (void) const = 0; + // Return the underlying proactor. + +protected: + ACE_Asynch_Operation_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Read_Stream_Impl : public virtual ACE_Asynch_Operation_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Read_Stream + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Read_Stream_Impl (void) {} + + virtual int read (ACE_Message_Block &message_block, + u_long bytes_to_read, + const void *act, + int priority) = 0; + // This starts off an asynchronous read. Upto <bytes_to_read> will + // be read and stored in the <message_block>. + +protected: + ACE_Asynch_Read_Stream_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Read_Stream_Result_Impl : public virtual ACE_Asynch_Result_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Read_Stream::Result class. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Read_Stream_Result_Impl () {} + + virtual u_long bytes_to_read (void) const = 0; + // The number of bytes which were requested at the start of the + // asynchronous read. + + virtual ACE_Message_Block &message_block (void) const = 0; + // Message block which contains the read data. + + virtual ACE_HANDLE handle (void) const = 0; + // I/O handle used for reading. + +protected: + ACE_Asynch_Read_Stream_Result_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Write_Stream_Impl : public virtual ACE_Asynch_Operation_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Write_Stream class. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Write_Stream_Impl (void) {} + + virtual int write (ACE_Message_Block &message_block, + u_long bytes_to_write, + const void *act, + int priority) = 0; + // This starts off an asynchronous write. Upto <bytes_to_write> + // will be written from the <message_block>. + +protected: + ACE_Asynch_Write_Stream_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Write_Stream_Result_Impl : public virtual ACE_Asynch_Result_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Write_Stream::Result. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Write_Stream_Result_Impl () {} + + virtual u_long bytes_to_write (void) const = 0; + // The number of bytes which were requested at the start of the + // asynchronous write. + + virtual ACE_Message_Block &message_block (void) const = 0; + // Message block that contains the data to be written. + + virtual ACE_HANDLE handle (void) const = 0; + // I/O handle used for writing. + +protected: + ACE_Asynch_Write_Stream_Result_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Read_File_Impl : public virtual ACE_Asynch_Read_Stream_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Read_File::Result. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Read_File_Impl () {} + + virtual int read (ACE_Message_Block &message_block, + u_long bytes_to_read, + u_long offset, + u_long offset_high, + const void *act, + int priority) = 0; + // This starts off an asynchronous read. Upto <bytes_to_read> will + // be read and stored in the <message_block>. The read will start + // at <offset> from the beginning of the file. + +protected: + ACE_Asynch_Read_File_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Read_File_Result_Impl : public virtual ACE_Asynch_Read_Stream_Result_Impl +{ + // = TITLE + // This is the abstract base class for all the concrete + // implementation classes for ACE_Asynch_Read_File::Result. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Read_File_Result_Impl () {} + // Destructor. + +protected: + ACE_Asynch_Read_File_Result_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Write_File_Impl : public virtual ACE_Asynch_Write_Stream_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Write_File. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Write_File_Impl (void) {} + + virtual int write (ACE_Message_Block &message_block, + u_long bytes_to_write, + u_long offset, + u_long offset_high, + const void *act, + int priority) = 0; + // This starts off an asynchronous write. Upto <bytes_to_write> + // will be write and stored in the <message_block>. The write will + // start at <offset> from the beginning of the file. + +protected: + ACE_Asynch_Write_File_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Write_File_Result_Impl : public virtual ACE_Asynch_Write_Stream_Result_Impl +{ + // = TITLE + // + // This is the abstract base class for all the concrete + // implementation classes that provide different implementations + // for the ACE_Asynch_Write_File::Result. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Write_File_Result_Impl () {} + +protected: + ACE_Asynch_Write_File_Result_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Accept_Impl : public virtual ACE_Asynch_Operation_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Accept. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Accept_Impl (void) {} + + virtual int accept (ACE_Message_Block &message_block, + u_long bytes_to_read, + ACE_HANDLE accept_handle, + const void *act, + int priority) = 0; + // This starts off an asynchronous accept. The asynchronous accept + // call also allows any initial data to be returned to the + // <handler>. Upto <bytes_to_read> will be read and stored in the + // <message_block>. The <accept_handle> will be used for the + // <accept> call. If (<accept_handle> == INVALID_HANDLE), a new + // handle will be created. + // + // <message_block> must be specified. This is because the address of + // the new connection is placed at the end of this buffer. + +protected: + ACE_Asynch_Accept_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Accept_Result_Impl : public virtual ACE_Asynch_Result_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Accept. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Accept_Result_Impl () {} + + virtual u_long bytes_to_read (void) const = 0; + // The number of bytes which were requested at the start of the + // asynchronous accept. + + virtual ACE_Message_Block &message_block (void) const = 0; + // Message block which contains the read data. + + virtual ACE_HANDLE listen_handle (void) const = 0; + // I/O handle used for accepting new connections. + + virtual ACE_HANDLE accept_handle (void) const = 0; + // I/O handle for the new connection. + +protected: + ACE_Asynch_Accept_Result_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Asynch_Transmit_File_Impl : public virtual ACE_Asynch_Operation_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Transmit_File. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Transmit_File_Impl () {} + + virtual int transmit_file (ACE_HANDLE file, + ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer, + u_long bytes_to_write, + u_long offset, + u_long offset_high, + u_long bytes_per_send, + u_long flags, + const void *act, + int priority) = 0; + // This starts off an asynchronous transmit file. + +protected: + ACE_Asynch_Transmit_File_Impl (void); + // Do-nothing constructor. +}; + +class ACE_Export ACE_Asynch_Transmit_File_Result_Impl : public virtual ACE_Asynch_Result_Impl +{ + // = TITLE + // + // Abstract base class for all the concrete implementation + // classes that provide different implementations for the + // ACE_Asynch_Transmit_File::Result. + // + // = DESCRIPTION + // +public: + virtual ~ACE_Asynch_Transmit_File_Result_Impl () {} + + virtual ACE_HANDLE socket (void) const = 0; + // Socket used for transmitting the file. + + virtual ACE_HANDLE file (void) const = 0; + // File from which the data is read. + + virtual ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer (void) const = 0; + // Header and trailer data associated with this transmit file. + + virtual u_long bytes_to_write (void) const = 0; + // The number of bytes which were requested at the start of the + // asynchronous transmit file. + + virtual u_long bytes_per_send (void) const = 0; + // Number of bytes per send requested at the start of the transmit + // file. + + virtual u_long flags (void) const = 0; + // Flags which were passed into transmit file. + +protected: + ACE_Asynch_Transmit_File_Result_Impl (void); + // Do-nothing constructor. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Asynch_IO_Impl.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HAS_AIO_CALLS || !ACE_HAS_WINCE && ACE_WIN32 */ +#endif /* ACE_ASYNCH_IO_IMPL_H */ diff --git a/ace/Asynch_IO_Impl.i b/ace/Asynch_IO_Impl.i new file mode 100644 index 00000000000..a6c36925943 --- /dev/null +++ b/ace/Asynch_IO_Impl.i @@ -0,0 +1,87 @@ +// $Id$ + +ACE_INLINE +ACE_Asynch_Result_Impl::ACE_Asynch_Result_Impl (void) +{ +} + +ACE_INLINE +ACE_Asynch_Operation_Impl::ACE_Asynch_Operation_Impl (void) +{ +} + +ACE_INLINE +ACE_Asynch_Read_Stream_Impl::ACE_Asynch_Read_Stream_Impl (void) + : ACE_Asynch_Operation_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Read_Stream_Result_Impl::ACE_Asynch_Read_Stream_Result_Impl (void) + : ACE_Asynch_Result_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Write_Stream_Impl::ACE_Asynch_Write_Stream_Impl (void) + : ACE_Asynch_Operation_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Write_Stream_Result_Impl::ACE_Asynch_Write_Stream_Result_Impl (void) + : ACE_Asynch_Result_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Read_File_Impl::ACE_Asynch_Read_File_Impl (void) + : ACE_Asynch_Operation_Impl (), + ACE_Asynch_Read_Stream_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Read_File_Result_Impl::ACE_Asynch_Read_File_Result_Impl (void) + : ACE_Asynch_Result_Impl (), + ACE_Asynch_Read_Stream_Result_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Write_File_Impl::ACE_Asynch_Write_File_Impl (void) + : ACE_Asynch_Operation_Impl (), + ACE_Asynch_Write_Stream_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Write_File_Result_Impl::ACE_Asynch_Write_File_Result_Impl (void) + : ACE_Asynch_Result_Impl (), + ACE_Asynch_Write_Stream_Result_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Accept_Impl::ACE_Asynch_Accept_Impl (void) + : ACE_Asynch_Operation_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Accept_Result_Impl::ACE_Asynch_Accept_Result_Impl (void) + : ACE_Asynch_Result_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Transmit_File_Impl::ACE_Asynch_Transmit_File_Impl (void) + : ACE_Asynch_Operation_Impl () +{ +} + +ACE_INLINE +ACE_Asynch_Transmit_File_Result_Impl::ACE_Asynch_Transmit_File_Result_Impl (void) + : ACE_Asynch_Result_Impl () +{ +} diff --git a/ace/POSIX_Asynch_IO.h b/ace/POSIX_Asynch_IO.h new file mode 100644 index 00000000000..e572d1d73df --- /dev/null +++ b/ace/POSIX_Asynch_IO.h @@ -0,0 +1,1085 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// +// ace +// +// = FILENAME +// +// POSIX_Asynch_IO.h +// +// = DESCRIPTION +// +// The implementation classes for POSIX implementation of Asynch +// Operations are defined here in this file. +// +// = AUTHOR +// +// Irfan Pyarali (irfan@cs.wustl.edu), +// Tim Harrison (harrison@cs.wustl.edu) and +// Alexander Babu Arulanthu <alex@cs.wustl.edu> +// +// ============================================================================ + +#if !defined (ACE_POSIX_ASYNCH_IO_H) +#define ACE_POSIX_ASYNCH_IO_H + +#include "ace/OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if defined (ACE_HAS_AIO_CALLS) + +#include "ace/Asynch_IO_Impl.h" +#include "ace/Reactor.h" + +// Forward declarations +class ACE_POSIX_SIG_Proactor; +class ACE_POSIX_AIOCB_Proactor; + +class ACE_Export ACE_POSIX_Asynch_Result : public virtual ACE_Asynch_Result_Impl, + public aiocb +{ + // = TITLE + // + // This class provides concrete implementation for + // ACE_Asynch_Result for POSIX4 platforms. This class extends + // <aiocb> and makes it more useful. + // + // = DESCRIPTION + // +public: + u_long bytes_transferred (void) const; + // Number of bytes transferred by the operation. + + const void *act (void) const; + // ACT associated with the operation. + + int success (void) const; + // Did the operation succeed? + + const void *completion_key (void) const; + // This is the ACT associated with the handle on which the + // Asynch_Operation takes place. + // + // @@ This is not implemented for POSIX4 platforms. + // + + u_long error (void) const; + // Error value if the operation fail. + + ACE_HANDLE event (void) const; + // This returns ACE_INVALID_HANDLE on POSIX4-Unix platforms. + + u_long offset (void) const; + u_long offset_high (void) const; + // This really make sense only when doing file I/O. + // + // @@ On POSIX4-Unix, offset_high should be supported using + // aiocb64. + // + + int priority (void) const; + // Priority of the operation. + + virtual ~ACE_POSIX_Asynch_Result (void); + // Destructor. + +protected: + ACE_POSIX_Asynch_Result (ACE_Handler &handler, + const void* act, + ACE_HANDLE event, + u_long offset, + u_long offset_high, + int priority); + // Constructor. <Event> is not used on POSIX. + + ACE_Handler &handler_; + // Handler that will be called back. + + const void *act_; + // ACT for this operation. + // We could use <aiocb::aio_sigevent.sigev_value.sival_ptr> for + // this. But it doesnot provide the constness, so this may be + // better. + + // aiocb::aio_resultp.aio_return + // Bytes transferred by this operation. + + int success_; + // Success indicator. + + const void *completion_key_; + // ACT associated with handle. + + // aiocb::aio_resultp.aio_errno + // Error if operation failed. +}; + +class ACE_Export ACE_POSIX_Asynch_Operation : public virtual ACE_Asynch_Operation_Impl +{ + // = TITLE + // + // This class abstracts out the common things needed for + // implementing Asynch_Operation for POSIX platforms. Specific + // implementations such as POSIX_AIOCB_Asynch_Operation and + // POSIX_SIG_Asynch_Operation etc., can derive from this class. + // + // = DESCRIPTION + // +public: + int open (ACE_Handler &handler, + ACE_HANDLE handle, + const void *completion_key, + ACE_Proactor *proactor); + // Initializes the factory with information which will be used with + // each asynchronous call. If (<handle> == ACE_INVALID_HANDLE), + // <ACE_Handler::handle> will be called on the <handler> to get the + // correct handle. + + int cancel (void); + // + // @@ Not implemented. Returns 0. + + // = Access methods. + + ACE_Proactor* proactor (void) const; + // Return the underlying proactor. + +protected: + ACE_POSIX_Asynch_Operation (void); + // No op contructor. + + virtual ~ACE_POSIX_Asynch_Operation (void); + // Destructor. + + ACE_Proactor *proactor_; + // Proactor that this Asynch IO will be registered with. + + ACE_Handler *handler_; + // Handler that will receive the callback. + + ACE_HANDLE handle_; + // I/O handle used for reading. +}; + +class ACE_Export ACE_POSIX_AIOCB_Asynch_Operation : public virtual ACE_POSIX_Asynch_Operation +{ + // = TITLE + // + // This class implements ACE_Asynch_Operation for AIOCB + // (Asynchronous I/O Control Blocks) based implementation of + // Proactor. + // + // = DESCRIPTION + // +protected: + ACE_POSIX_AIOCB_Asynch_Operation (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor); + // Contructor. + + virtual ~ACE_POSIX_AIOCB_Asynch_Operation (void); + // Destructor. + + int register_aio_with_proactor (aiocb *aiocb_ptr); + // This call is for the POSIX implementation. This method is used by + // <ACE_Asynch_Operation> to store some information with the + // Proactor after an <aio_> call is issued, so that the Proactor can + // retrive this information to do <aio_return> and <aio_error>. + // Passing a '0' ptr returns the status, indicating whether there + // are slots available or no. Passing a valid ptr stores the ptr + // with the Proactor. + + ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor_; + // It is easy to get this specific implementation proactor here, + // since it is the one that creates the correct POSIX_Asynch_* + // objects. We can use this to get to the implementation proactor + // directly. +}; + +class ACE_Export ACE_POSIX_SIG_Asynch_Operation : public virtual ACE_POSIX_Asynch_Operation +{ + // = TITLE + // + // This class implements ACE_Asynch_Operation for Real-Time + // Signal (<sigtimedwait>) based implementation of Proactor. + // + // = DESCRIPTION + // +protected: + ACE_POSIX_SIG_Asynch_Operation (ACE_POSIX_SIG_Proactor *posix_sig_proactor); + // Contructor. + + virtual ~ACE_POSIX_SIG_Asynch_Operation (void); + // Destructor. + + ACE_POSIX_SIG_Proactor *posix_sig_proactor_; + // It is easy to get this specific implementation proactor here, + // since it is the one that creates the correct POSIX_Asynch_* + // objects. We can use this to get to the implementation proactor + // directly. +}; + +class ACE_Export ACE_POSIX_Asynch_Read_Stream_Result : public virtual ACE_Asynch_Read_Stream_Result_Impl, + public ACE_POSIX_Asynch_Result +{ + // = TITLE + // + // This class provides concrete implementation for + // ACE_Asynch_Read_Stream::Result class for POSIX platforms. + // + // = DESCRIPTION + // + + friend class ACE_POSIX_AIOCB_Asynch_Read_Stream; + friend class ACE_POSIX_SIG_Asynch_Read_Stream; + // Factory classes willl have special permissions. + + friend class ACE_POSIX_Proactor; + // The Proactor constructs the Result class for faking results. + +public: + u_long bytes_to_read (void) const; + // The number of bytes which were requested at the start of the + // asynchronous read. + + ACE_Message_Block &message_block (void) const; + // Message block which contains the read data. + + ACE_HANDLE handle (void) const; + // I/O handle used for reading. + +protected: + ACE_POSIX_Asynch_Read_Stream_Result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + u_long bytes_to_read, + const void* act, + ACE_HANDLE event, + int priority); + // Constructor is protected since creation is limited to + // ACE_Asynch_Read_Stream factory. + + virtual void complete (u_long bytes_transferred, + int success, + const void *completion_key, + u_long error); + // Get the data copied to this class, before calling application + // handler. + + virtual ~ACE_POSIX_Asynch_Read_Stream_Result (void); + // Destrcutor. + + // aiocb::aio_nbytes + // Bytes requested when the asynchronous read was initiated. + + ACE_Message_Block &message_block_; + // Message block for reading the data into. + + // aiocb::aio_filedes + // I/O handle used for reading. +}; + +class ACE_Export ACE_POSIX_AIOCB_Asynch_Read_Stream : public virtual ACE_Asynch_Read_Stream_Impl, + public ACE_POSIX_AIOCB_Asynch_Operation +{ + // = TITLE + // + // This class implements ACE_Asynch_Read_Stream for AIOCB + // (Asynchronous I/O Control Blocks) based implementation of + // Proactor. + // + // = DESCRIPTION + // +public: + ACE_POSIX_AIOCB_Asynch_Read_Stream (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor); + // Constructor. + + int read (ACE_Message_Block &message_block, + u_long bytes_to_read, + const void *act, + int priority); + // This starts off an asynchronous read. Upto <bytes_to_read> will + // be read and stored in the <message_block>. + + virtual ~ACE_POSIX_AIOCB_Asynch_Read_Stream (void); + // Destructor. + +protected: + int shared_read (ACE_POSIX_Asynch_Read_Stream_Result *result); + // This is the method which does the real work and is there so that + // the ACE_Asynch_Read_File class can use it too. +}; + + +class ACE_Export ACE_POSIX_SIG_Asynch_Read_Stream : public virtual ACE_Asynch_Read_Stream_Impl, + public ACE_POSIX_SIG_Asynch_Operation +{ + // = TITLE + // + // This class implements ACE_Asynch_Read_Stream for Real-Time + // Signal (<sigtimedwait>) based implementation of Proactor. + // + // = DESCRIPTION + // +public: + ACE_POSIX_SIG_Asynch_Read_Stream (ACE_POSIX_SIG_Proactor *posix_sig_proactor); + // Constructor. + + int read (ACE_Message_Block &message_block, + u_long bytes_to_read, + const void *act, + int priority); + // This starts off an asynchronous read. Upto <bytes_to_read> will + // be read and stored in the <message_block>. + + virtual ~ACE_POSIX_SIG_Asynch_Read_Stream (void); + // Destructor. + +protected: + int shared_read (ACE_POSIX_Asynch_Read_Stream_Result *result); + // This is the method which does the real work and is there so that + // the ACE_Asynch_Read_File class can use it too. +}; + +class ACE_Export ACE_POSIX_Asynch_Write_Stream_Result : public virtual ACE_Asynch_Write_Stream_Result_Impl, + public ACE_POSIX_Asynch_Result +{ + // = TITLE + // + // This class provides concrete implementation for + // ACE_Asynch_Write_Stream::Result on POSIX platforms. + // + // = DESCRIPTION + // + // This class has all the information necessary for the + // <handler> to uniquiely identify the completion of the + // asynchronous write. + + friend class ACE_POSIX_AIOCB_Asynch_Write_Stream; + friend class ACE_POSIX_SIG_Asynch_Write_Stream; + // Factory classes will have special privilages. + + friend class ACE_POSIX_Proactor; + // The Proactor constructs the Result class for faking results. + +public: + u_long bytes_to_write (void) const; + // The number of bytes which were requested at the start of the + // asynchronous write. + + ACE_Message_Block &message_block (void) const; + // Message block that contains the data to be written. + + ACE_HANDLE handle (void) const; + // I/O handle used for writing. + +protected: + ACE_POSIX_Asynch_Write_Stream_Result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + u_long bytes_to_write, + const void* act, + ACE_HANDLE event, + int priority); + // Constructor is protected since creation is limited to + // ACE_Asynch_Write_Stream factory. + + virtual void complete (u_long bytes_transferred, + int success, + const void *completion_key, + u_long error); + // ACE_Proactor will call this method when the write completes. + + virtual ~ACE_POSIX_Asynch_Write_Stream_Result (void); + // Destructor. + +protected: + // aiocb::aio_nbytes + // The number of bytes which were requested at the start of the + // asynchronous write. + + ACE_Message_Block &message_block_; + // Message block that contains the data to be written. + + // aiocb::aio_filedes + // I/O handle used for writing. +}; + +class ACE_Export ACE_POSIX_AIOCB_Asynch_Write_Stream : public virtual ACE_Asynch_Write_Stream_Impl, + public ACE_POSIX_AIOCB_Asynch_Operation +{ + // = TITLE + // + // This class implements ACE_Asynch_Write_Stream for AIOCB + // (Asynchronous I/O Control Blocks) based implementation of + // Proactor. + // + // = DESCRIPTION + // +public: + ACE_POSIX_AIOCB_Asynch_Write_Stream (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor); + // Constructor. + + int write (ACE_Message_Block &message_block, + u_long bytes_to_write, + const void *act, + int priority); + // This starts off an asynchronous write. Upto <bytes_to_write> + // will be written from the <message_block>. + + virtual ~ACE_POSIX_AIOCB_Asynch_Write_Stream (void); + // Destrcutor. + +protected: + int shared_write (ACE_POSIX_Asynch_Write_Stream_Result *result); + // This is the method which does the real work and is there so that + // the ACE_Asynch_Write_File class can use it too. +}; + +class ACE_Export ACE_POSIX_SIG_Asynch_Write_Stream : public virtual ACE_Asynch_Write_Stream_Impl, + public ACE_POSIX_SIG_Asynch_Operation +{ + // = TITLE + // + // This class implements ACE_Asynch_Write_Stream for Real-Time + // Signal (<sigtimedwait>) based implementation of Proactor. + // + // = DESCRIPTION + // +public: + ACE_POSIX_SIG_Asynch_Write_Stream (ACE_POSIX_SIG_Proactor *posix_sig_proactor); + // Constrctor. + + int write (ACE_Message_Block &message_block, + u_long bytes_to_write, + const void *act, + int priority); + // This starts off an asynchronous write. Upto <bytes_to_write> + // will be written from the <message_block>. + + virtual ~ACE_POSIX_SIG_Asynch_Write_Stream (void); + // Destructor. + +protected: + int shared_write (ACE_POSIX_Asynch_Write_Stream_Result *result); + // This is the method which does the real work and is there so that + // the ACE_Asynch_Write_File class can use it too. +}; + +class ACE_Export ACE_POSIX_Asynch_Read_File_Result : public virtual ACE_Asynch_Read_File_Result_Impl, + public ACE_POSIX_Asynch_Read_Stream_Result +{ + // = TITLE + // + // This class provides concrete implementation for + // ACE_Asynch_Read_File::Result class for POSIX platforms. + // + // = DESCRIPTION + // + + friend class ACE_POSIX_AIOCB_Asynch_Read_File; + friend class ACE_POSIX_SIG_Asynch_Read_File; + // Factory classes willl have special permissions. + + friend class ACE_POSIX_Proactor; + // The Proactor constructs the Result class for faking results. + +protected: + ACE_POSIX_Asynch_Read_File_Result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + u_long bytes_to_read, + const void* act, + u_long offset, + u_long offset_high, + ACE_HANDLE event, + int priority); + // Constructor is protected since creation is limited to + // ACE_Asynch_Read_File factory. + + virtual void complete (u_long bytes_transferred, + int success, + const void *completion_key, + u_long error); + // ACE_Proactor will call this method when the read completes. + + virtual ~ACE_POSIX_Asynch_Read_File_Result (void); + // Destructor. +}; + +class ACE_Export ACE_POSIX_AIOCB_Asynch_Read_File : public virtual ACE_Asynch_Read_File_Impl, + public ACE_POSIX_AIOCB_Asynch_Read_Stream +{ + // = TITLE + // + // This class is a factory for starting off asynchronous reads + // on a file. This class implements ACE_Asynch_Read_File for + // AIOCB (Asynchronous I/O Control Blocks) based implementation + // of Proactor. + // + // = DESCRIPTION + // + // Once <open> is called, multiple asynchronous <read>s can + // started using this class. A ACE_Asynch_Read_File::Result + // will be passed back to the <handler> when the asynchronous + // reads completes through the <ACE_Handler::handle_read_file> + // callback. + // + // This class differs slightly from ACE_Asynch_Read_Stream as it + // allows the user to specify an offset for the read. + +public: + ACE_POSIX_AIOCB_Asynch_Read_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor); + // Constructor. + + int read (ACE_Message_Block &message_block, + u_long bytes_to_read, + u_long offset, + u_long offset_high, + const void *act, + int priority); + // This starts off an asynchronous read. Upto <bytes_to_read> will + // be read and stored in the <message_block>. The read will start + // at <offset> from the beginning of the file. + + virtual ~ACE_POSIX_AIOCB_Asynch_Read_File (void); + // Destructor. + +private: + int read (ACE_Message_Block &message_block, + u_long bytes_to_read, + const void *act, + int priority); + // This belongs to ACE_POSIX_AIOCB_Asynch_Read_Stream. We have + // defined this here to avoid compiler warnings and forward the + // method to <ACE_POSIX_AIOCB_Asynch_Read_Stream::read>. +}; + +class ACE_Export ACE_POSIX_SIG_Asynch_Read_File : public virtual ACE_Asynch_Read_File_Impl, + public ACE_POSIX_SIG_Asynch_Read_Stream +{ + // = TITLE + // + // This class is a factory for starting off asynchronous reads + // on a file. This class implements ACE_Asynch_Operation for + // Real-Time Signal (<sigtimedwait>) based implementation of + // Proactor. + // + // = DESCRIPTION + // + // Once <open> is called, multiple asynchronous <read>s can + // started using this class. A ACE_Asynch_Read_File::Result + // will be passed back to the <handler> when the asynchronous + // reads completes through the <ACE_Handler::handle_read_file> + // callback. + +public: + ACE_POSIX_SIG_Asynch_Read_File (ACE_POSIX_SIG_Proactor *posix_sig_proactor); + // Constructor. + + int read (ACE_Message_Block &message_block, + u_long bytes_to_read, + u_long offset, + u_long offset_high, + const void *act, + int priority); + // This starts off an asynchronous read. Upto <bytes_to_read> will + // be read and stored in the <message_block>. The read will start + // at <offset> from the beginning of the file. + + virtual ~ACE_POSIX_SIG_Asynch_Read_File (void); + // Destructor. + +private: + int read (ACE_Message_Block &message_block, + u_long bytes_to_read, + const void *act, + int priority); + // This belongs to ACE_POSIX_SIG_Asynch_Read_Stream. We have + // defined this here to avoid compiler warnings and forward the + // method to <ACE_POSIX_SIG_Asynch_Read_Stream::read>. +}; + +class ACE_Export ACE_POSIX_Asynch_Write_File_Result : public virtual ACE_Asynch_Write_File_Result_Impl, + public ACE_POSIX_Asynch_Write_Stream_Result +{ + // = TITLE + // + // This class provides implementation for + // ACE_Asynch_Write_File_Result for POSIX platforms. + // + // = DESCRIPTION + // + // This class has all the information necessary for the + // <handler> to uniquiely identify the completion of the + // asynchronous write. + // + // This class differs slightly from + // ACE_Asynch_Write_Stream::Result as it calls back + // <ACE_Handler::handle_write_file> on the <handler> instead + // of <ACE_Handler::handle_write_stream>. No additional state + // is required by this class as ACE_Asynch_Result can store + // the <offset>. + + friend class ACE_POSIX_AIOCB_Asynch_Write_File; + friend class ACE_POSIX_SIG_Asynch_Write_File; + // Factory classes will have special permissions. + + friend class ACE_POSIX_Proactor; + // The Proactor constructs the Result class for faking results. + +protected: + ACE_POSIX_Asynch_Write_File_Result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + u_long bytes_to_write, + const void* act, + u_long offset, + u_long offset_high, + ACE_HANDLE event, + int priority); + // Constructor is protected since creation is limited to + // ACE_Asynch_Write_File factory. + + virtual void complete (u_long bytes_transferred, + int success, + const void *completion_key, + u_long error); + // ACE_Proactor will call this method when the write completes. + + virtual ~ACE_POSIX_Asynch_Write_File_Result (void); + // Destructor. +}; + +class ACE_Export ACE_POSIX_AIOCB_Asynch_Write_File : public virtual ACE_Asynch_Write_File_Impl, + public ACE_POSIX_AIOCB_Asynch_Write_Stream +{ + // = TITLE + // + // This class provides concrete implementation for + // ACE_Asynch_Write_File for POSIX platforms where the + // completion strategy for Proactor is based on AIOCB (AIO + // Control Blocks). + // + // = DESCRIPTION + // +public: + ACE_POSIX_AIOCB_Asynch_Write_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor); + // Constructor. + + int write (ACE_Message_Block &message_block, + u_long bytes_to_write, + u_long offset, + u_long offset_high, + const void *act, + int priority); + // This starts off an asynchronous write. Upto <bytes_to_write> + // will be write and stored in the <message_block>. The write will + // start at <offset> from the beginning of the file. + + virtual ~ACE_POSIX_AIOCB_Asynch_Write_File (void); + // Destructor. + +private: + int write (ACE_Message_Block &message_block, + u_long bytes_to_write, + const void *act, + int priority); + // This <write> belongs to ACE_POSIX_SIG_Asynch_Write_Stream. We + // have put this here to avoid compiler warnings. We forward this + // method call to the <ACE_POSIX_SIG_Asynch_Write_Stream::write> + // one. +}; + +class ACE_Export ACE_POSIX_SIG_Asynch_Write_File : public virtual ACE_Asynch_Write_File_Impl, + public ACE_POSIX_SIG_Asynch_Write_Stream +{ + // = TITLE + // + // This class is a factory for starting off asynchronous reads + // on a file. This class implements ACE_Asynch_Operation for + // Real-Time Signal (<sigtimedwait>) based implementation of + // Proactor. + // + // = DESCRIPTION + // + // Once <open> is called, multiple asynchronous <read>s can + // started using this class. A ACE_Asynch_Read_File::Result + // will be passed back to the <handler> when the asynchronous + // reads completes through the <ACE_Handler::handle_read_file> + // callback. + +public: + ACE_POSIX_SIG_Asynch_Write_File (ACE_POSIX_SIG_Proactor *posix_sig_proactor); + // Constructor. + + int write (ACE_Message_Block &message_block, + u_long bytes_to_write, + u_long offset, + u_long offset_high, + const void *act, + int priority); + // This starts off an asynchronous write. Upto <bytes_to_write> + // will be write and stored in the <message_block>. The write will + // start at <offset> from the beginning of the file. + + virtual ~ACE_POSIX_SIG_Asynch_Write_File (void); + // Destrcutor. + +private: + int write (ACE_Message_Block &message_block, + u_long bytes_to_write, + const void *act, + int priority); + // This <write> belongs to ACE_POSIX_SIG_Asynch_Write_Stream. We + // have put this here to avoid compiler warnings. We forward this + // method call to the <ACE_POSIX_SIG_Asynch_Write_Stream::write> + // one. +}; + +class ACE_Export ACE_POSIX_Asynch_Accept_Result : public virtual ACE_Asynch_Accept_Result_Impl, + public ACE_POSIX_Asynch_Result +{ + // = TITLE + // + // This is that class which will be passed back to the + // <handler> when the asynchronous accept completes. + // + // = DESCRIPTION + // + // This class has all the information necessary for the + // <handler> to uniquiely identify the completion of the + // asynchronous accept. + + friend class ACE_POSIX_AIOCB_Asynch_Accept; + friend class ACE_POSIX_SIG_Asynch_Accept; + // Factory classes willl have special permissions. + + friend class ACE_POSIX_Proactor; + // The Proactor constructs the Result class for faking results. + +public: + u_long bytes_to_read (void) const; + // The number of bytes which were requested at the start of the + // asynchronous accept. + + ACE_Message_Block &message_block (void) const; + // Message block which contains the read data. + + ACE_HANDLE listen_handle (void) const; + // I/O handle used for accepting new connections. + + ACE_HANDLE accept_handle (void) const; + // I/O handle for the new connection. + +protected: + ACE_POSIX_Asynch_Accept_Result (ACE_Handler &handler, + ACE_HANDLE listen_handle, + ACE_HANDLE accept_handle, + ACE_Message_Block &message_block, + u_long bytes_to_read, + const void* act, + ACE_HANDLE event, + int priority); + // Constructor is protected since creation is limited to + // ACE_Asynch_Accept factory. + + virtual void complete (u_long bytes_transferred, + int success, + const void *completion_key, + u_long error); + // ACE_Proactor will call this method when the accept completes. + + virtual ~ACE_POSIX_Asynch_Accept_Result (void); + // Destructor. + + // aiocb::aio_nbytes + // Bytes requested when the asynchronous read was initiated. + // Actually, on POSIX implementation, we dont read any intial data. + + ACE_Message_Block &message_block_; + // Message block for reading the data into. + + ACE_HANDLE listen_handle_; + // I/O handle used for accepting new connections. + + // aiocb::aio_filedes + // I/O handle for the new connection. +}; + +class ACE_POSIX_AIOCB_Asynch_Accept_Handler; +// Forward declaration. This class is defined the in the cpp file, +// since this is internal to the implementation. + +class ACE_Export ACE_POSIX_AIOCB_Asynch_Accept : public virtual ACE_Asynch_Accept_Impl, + public ACE_POSIX_AIOCB_Asynch_Operation +{ +public: + ACE_POSIX_AIOCB_Asynch_Accept (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor); + // Constructor. + + int open (ACE_Handler &handler, + ACE_HANDLE handle, + const void *completion_key, + ACE_Proactor *proactor); + // This <open> belongs to ACE_AIOCB_Asynch_Operation. We forward + // this call to that method. We have put this here to avoid the + // compiler warnings. + + int accept (ACE_Message_Block &message_block, + u_long bytes_to_read, + ACE_HANDLE accept_handle, + const void *act, + int priority); + // This starts off an asynchronous accept. The asynchronous accept + // call also allows any initial data to be returned to the + // <handler>. Upto <bytes_to_read> will be read and stored in the + // <message_block>. The <accept_handle> will be used for the + // <accept> call. If (<accept_handle> == INVALID_HANDLE), a new + // handle will be created. + // + // <message_block> must be specified. This is because the address of + // the new connection is placed at the end of this buffer. + + virtual ~ACE_POSIX_AIOCB_Asynch_Accept (void); + // Destructor. + +private: + static void* thread_function (void* reactor); + // The thread function that does handle events. + + ACE_Reactor reactor_; + // Reactor to wait on the <listen_handle>. + + ACE_POSIX_AIOCB_Asynch_Accept_Handler* accept_handler_; + // The Event Handler to do handle_input. +}; + +class ACE_POSIX_SIG_Asynch_Accept_Handler; +// Forward declaration. This class is defined the in the cpp file, +// since this is internal to the implementation. + +class ACE_Export ACE_POSIX_SIG_Asynch_Accept : public virtual ACE_Asynch_Accept_Impl, + public ACE_POSIX_SIG_Asynch_Operation +{ + // = TITLE + // + // This class implements ACE_Asynch_Accept for Real-Time + // Signal (<sigtimedwait>) based implementation of Proactor. + // + // = DESCRIPTION + // +public: + ACE_POSIX_SIG_Asynch_Accept (ACE_POSIX_SIG_Proactor *posix_sig_proactor); + // Constructor. + + int open (ACE_Handler &handler, + ACE_HANDLE handle, + const void *completion_key, + ACE_Proactor *proactor); + // This <open> belongs to ACE_SIG_Asynch_Operation. We forward this + // call to that method. We have put this here to avoid the compiler + // warnings. + + int accept (ACE_Message_Block &message_block, + u_long bytes_to_read, + ACE_HANDLE accept_handle, + const void *act, + int priority); + // This starts off an asynchronous accept. The asynchronous accept + // call also allows any initial data to be returned to the + // <handler>. Upto <bytes_to_read> will be read and stored in the + // <message_block>. The <accept_handle> will be used for the + // <accept> call. If (<accept_handle> == INVALID_HANDLE), a new + // handle will be created. + // + // <message_block> must be specified. This is because the address of + // the new connection is placed at the end of this buffer. + + virtual ~ACE_POSIX_SIG_Asynch_Accept (void); + // Destructor. + +private: + static void* thread_function (void* reactor); + // The thread function that does handle events. + + ACE_Reactor reactor_; + // Reactor to wait on the <listen_handle>. + + ACE_POSIX_SIG_Asynch_Accept_Handler* accept_handler_; + // The Event Handler to do handle_input. +}; + +class ACE_Export ACE_POSIX_Asynch_Transmit_File_Result : public virtual ACE_Asynch_Transmit_File_Result_Impl, + public ACE_POSIX_Asynch_Result +{ + // = TITLE + // + // This is that class which will be passed back to the + // <handler> when the asynchronous transmit file completes. + // + // = DESCRIPTION + // + // This class has all the information necessary for the + // <handler> to uniquiely identify the completion of the + // asynchronous transmit file. + + friend class ACE_POSIX_AIOCB_Asynch_Transmit_File; + friend class ACE_POSIX_SIG_Asynch_Transmit_File; + // Factory classes willl have special permissions. + + friend class ACE_POSIX_Asynch_Transmit_Handler; + friend class ACE_POSIX_AIOCB_Asynch_Transmit_Handler; + friend class ACE_POSIX_SIG_Asynch_Transmit_Handler; + // Handlers do all the job. + + friend class ACE_POSIX_Proactor; + // The Proactor constructs the Result class for faking results. + +public: + ACE_HANDLE socket (void) const; + // Socket used for transmitting the file. + + ACE_HANDLE file (void) const; + // File from which the data is read. + + ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer (void) const; + // Header and trailer data associated with this transmit file. + + u_long bytes_to_write (void) const; + // The number of bytes which were requested at the start of the + // asynchronous transmit file. + + u_long bytes_per_send (void) const; + // Number of bytes per send requested at the start of the transmit + // file. + + u_long flags (void) const; + // Flags which were passed into transmit file. + +protected: + ACE_POSIX_Asynch_Transmit_File_Result (ACE_Handler &handler, + ACE_HANDLE socket, + ACE_HANDLE file, + ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer, + u_long bytes_to_write, + u_long offset, + u_long offset_high, + u_long bytes_per_send, + u_long flags, + const void *act, + ACE_HANDLE event, + int priority); + // Constructor is protected since creation is limited to + // ACE_Asynch_Transmit_File factory. + + virtual void complete (u_long bytes_transferred, + int success, + const void *completion_key, + u_long error); + // ACE_Proactor will call this method when the write completes. + + virtual ~ACE_POSIX_Asynch_Transmit_File_Result (void); + // Destructor. + + ACE_HANDLE socket_; + // Network I/O handle. + + // aiocb::aio_filedes + // File I/O handle. + + ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer_; + // Header and trailer data associated with this transmit file. + + // aiocb::aio_nbytes + // The number of bytes which were requested at the start of the + // asynchronous transmit file. + + u_long bytes_per_send_; + // Number of bytes per send requested at the start of the transmit + // file. + + u_long flags_; + // Flags which were passed into transmit file. +}; + +class ACE_Export ACE_POSIX_AIOCB_Asynch_Transmit_File : public virtual ACE_Asynch_Transmit_File_Impl, + public ACE_POSIX_AIOCB_Asynch_Operation +{ + // = DESCRIPTION + // Implementation for transmit_file will make use of + // POSIX_AIOCB_Asynch_Transmit_Handler. +public: + ACE_POSIX_AIOCB_Asynch_Transmit_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor); + // Constructor. + + int transmit_file (ACE_HANDLE file, + ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer, + u_long bytes_to_write, + u_long offset, + u_long offset_high, + u_long bytes_per_send, + u_long flags, + const void *act, + int priority); + // This starts off an asynchronous transmit file. The <file> is a + // handle to an open file. <header_and_trailer> is a pointer to a + // data structure that contains pointers to data to send before and + // after the file data is sent. Set this parameter to 0 if you only + // want to transmit the file data. Upto <bytes_to_write> will be + // written to the <socket>. If you want to send the entire file, + // let <bytes_to_write> = 0. <bytes_per_send> is the size of each + // block of data sent per send operation. Please read the Win32 + // documentation on what the flags should be. + + virtual ~ACE_POSIX_AIOCB_Asynch_Transmit_File (void); + // Destructor. +}; + +class ACE_Export ACE_POSIX_SIG_Asynch_Transmit_File : public virtual ACE_Asynch_Transmit_File_Impl, + public ACE_POSIX_SIG_Asynch_Operation +{ + // = TITLE + // + // This class implements ACE_Asynch_Transmit_File for Real-Time + // Signal (<sigtimedwait>) based implementation of Proactor. + // + // = DESCRIPTION + // +public: + ACE_POSIX_SIG_Asynch_Transmit_File (ACE_POSIX_SIG_Proactor *posix_sig_proactor); + // Constructor. + + int transmit_file (ACE_HANDLE file, + ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer, + u_long bytes_to_write, + u_long offset, + u_long offset_high, + u_long bytes_per_send, + u_long flags, + const void *act, + int priority); + // This starts off an asynchronous transmit file. The <file> is a + // handle to an open file. <header_and_trailer> is a pointer to a + // data structure that contains pointers to data to send before and + // after the file data is sent. Set this parameter to 0 if you only + // want to transmit the file data. Upto <bytes_to_write> will be + // written to the <socket>. If you want to send the entire file, + // let <bytes_to_write> = 0. <bytes_per_send> is the size of each + // block of data sent per send operation. + + virtual ~ACE_POSIX_SIG_Asynch_Transmit_File (void); + // Destructor. +}; + +#if defined (__ACE_INLINE__) +#include "ace/POSIX_Asynch_IO.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HAS_AIO_CALLS */ +#endif /* ACE_POSIX_ASYNCH_IO_H */ diff --git a/ace/POSIX_Proactor.cpp b/ace/POSIX_Proactor.cpp new file mode 100644 index 00000000000..05bac013d1c --- /dev/null +++ b/ace/POSIX_Proactor.cpp @@ -0,0 +1,1138 @@ +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/POSIX_Proactor.h" + +#if defined (ACE_HAS_AIO_CALLS) + +#include "ace/Task_T.h" +#include "ace/Log_Msg.h" +#include "ace/Object_Manager.h" + +#if !defined (__ACE_INLINE__) +#include "ace/POSIX_Proactor.i" +#endif /* __ACE_INLINE__ */ + +ACE_POSIX_Proactor::~ACE_POSIX_Proactor (void) +{ +} + +int +ACE_POSIX_Proactor::close (void) +{ +#if 0 + // Take care of the timer handler + if (this->timer_handler_) + { + delete this->timer_handler_; + this->timer_handler_ = 0; + } + + // Take care of the timer queue + if (this->delete_timer_queue_) + { + delete this->timer_queue_; + this->timer_queue_ = 0; + this->delete_timer_queue_ = 0; + } +#endif /* 0 */ + return 0; +} + +int +ACE_POSIX_Proactor::register_handle (ACE_HANDLE handle, + const void *completion_key) +{ + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (completion_key); + return 0; +} + +long +ACE_POSIX_Proactor::schedule_timer (ACE_Handler &handler, + const void *act, + const ACE_Time_Value &time) +{ + return this->schedule_timer (handler, + act, + time, + ACE_Time_Value::zero); +} + +long +ACE_POSIX_Proactor::schedule_repeating_timer (ACE_Handler &handler, + const void *act, + const ACE_Time_Value &interval) +{ + return this->schedule_timer (handler, + act, + interval, + interval); +} + +long +ACE_POSIX_Proactor::schedule_timer (ACE_Handler &handler, + const void *act, + const ACE_Time_Value &time, + const ACE_Time_Value &interval) +{ + ACE_UNUSED_ARG (handler); + ACE_UNUSED_ARG (act); + ACE_UNUSED_ARG (time); + ACE_UNUSED_ARG (interval); + ACE_NOTSUP_RETURN ((long) -1); + +#if 0 + // absolute time. + ACE_Time_Value absolute_time = + this->timer_queue_->gettimeofday () + time; + + // Only one guy goes in here at a time + ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->timer_queue_->mutex (), -1); + + // Schedule the timer + long result = this->timer_queue_->schedule (&handler, + act, + absolute_time, + interval); + if (result != -1) + { + // no failures: check to see if we are the earliest time + if (this->timer_queue_->earliest_time () == absolute_time) + + // wake up the timer thread + if (this->timer_handler_->timer_event_.signal () == -1) + { + // Cancel timer + this->timer_queue_->cancel (result); + result = -1; + } + } + return result; +#endif /* 0 */ +} + +int +ACE_POSIX_Proactor::cancel_timer (long timer_id, + const void **arg, + int dont_call_handle_close) +{ + ACE_NOTSUP_RETURN (-1); +#if 0 + // No need to singal timer event here. Even if the cancel timer was + // the earliest, we will have an extra wakeup. + return this->timer_queue_->cancel (timer_id, + arg, + dont_call_handle_close); +#endif /* 0 */ +} + +int +ACE_POSIX_Proactor::cancel_timer (ACE_Handler &handler, + int dont_call_handle_close) +{ + ACE_NOTSUP_RETURN (-1); +#if 0 + // No need to signal timer event here. Even if the cancel timer was + // the earliest, we will have an extra wakeup. + return this->timer_queue_->cancel (&handler, + dont_call_handle_close); +#endif /* 0 */ +} + +int +ACE_POSIX_Proactor::post_completion (ACE_POSIX_Asynch_Result *result) +{ + ACE_UNUSED_ARG (result); + return 0; +} + +#if 0 +int +ACE_POSIX_Proactor::handle_signal (int, siginfo_t *, ucontext_t *) +{ + // Perform a non-blocking "poll" for all the I/O events that have + // completed in the I/O completion queue. + + ACE_Time_Value timeout (0, 0); + int result = 0; + + while (1) + { + result = this->handle_events (timeout); + if (result != 0 || errno == ETIME) + break; + } + + // If our handle_events failed, we'll report a failure to the + // Reactor. + return result == -1 ? -1 : 0; +} + +int +ACE_POSIX_Proactor::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask close_mask) +{ + ACE_UNUSED_ARG (close_mask); + ACE_UNUSED_ARG (handle); + + return this->close (); +} +#endif /* 0 */ + +ACE_HANDLE +ACE_POSIX_Proactor::get_handle (void) const +{ + // @@ Implement this. + return ACE_INVALID_HANDLE; +} + +ACE_Asynch_Read_Stream_Result_Impl * +ACE_POSIX_Proactor::create_asynch_read_stream_result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + u_long bytes_to_read, + const void* act, + ACE_HANDLE event, + int priority) +{ + ACE_Asynch_Read_Stream_Result_Impl *implementation; + ACE_NEW_RETURN (implementation, + ACE_POSIX_Asynch_Read_Stream_Result (handler, + handle, + message_block, + bytes_to_read, + act, + event, + priority), + 0); + return implementation; +} + +ACE_Asynch_Write_Stream_Result_Impl * +ACE_POSIX_Proactor::create_asynch_write_stream_result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + u_long bytes_to_write, + const void* act, + ACE_HANDLE event, + int priority) +{ + ACE_Asynch_Write_Stream_Result_Impl *implementation; + ACE_NEW_RETURN (implementation, + ACE_POSIX_Asynch_Write_Stream_Result (handler, + handle, + message_block, + bytes_to_write, + act, + event, + priority), + 0); + return implementation; +} + +ACE_Asynch_Read_File_Result_Impl * +ACE_POSIX_Proactor::create_asynch_read_file_result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + u_long bytes_to_read, + const void* act, + u_long offset, + u_long offset_high, + ACE_HANDLE event, + int priority) +{ + ACE_Asynch_Read_File_Result_Impl *implementation; + ACE_NEW_RETURN (implementation, + ACE_POSIX_Asynch_Read_File_Result (handler, + handle, + message_block, + bytes_to_read, + act, + offset, + offset_high, + event, + priority), + 0); + return implementation; +} + +ACE_Asynch_Write_File_Result_Impl * +ACE_POSIX_Proactor::create_asynch_write_file_result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + u_long bytes_to_write, + const void* act, + u_long offset, + u_long offset_high, + ACE_HANDLE event, + int priority) +{ + ACE_Asynch_Write_File_Result_Impl *implementation; + ACE_NEW_RETURN (implementation, + ACE_POSIX_Asynch_Write_File_Result (handler, + handle, + message_block, + bytes_to_write, + act, + offset, + offset_high, + event, + priority), + 0); + return implementation; +} + +ACE_Asynch_Accept_Result_Impl * +ACE_POSIX_Proactor::create_asynch_accept_result (ACE_Handler &handler, + ACE_HANDLE listen_handle, + ACE_HANDLE accept_handle, + ACE_Message_Block &message_block, + u_long bytes_to_read, + const void* act, + ACE_HANDLE event, + int priority) +{ + ACE_Asynch_Accept_Result_Impl *implementation; + ACE_NEW_RETURN (implementation, + ACE_POSIX_Asynch_Accept_Result (handler, + listen_handle, + accept_handle, + message_block, + bytes_to_read, + act, + event, + priority), + 0); + return implementation; +} + +ACE_Asynch_Transmit_File_Result_Impl * +ACE_POSIX_Proactor::create_asynch_transmit_file_result (ACE_Handler &handler, + ACE_HANDLE socket, + ACE_HANDLE file, + ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer, + u_long bytes_to_write, + u_long offset, + u_long offset_high, + u_long bytes_per_send, + u_long flags, + const void *act, + ACE_HANDLE event, + int priority) +{ + ACE_Asynch_Transmit_File_Result_Impl *implementation; + ACE_NEW_RETURN (implementation, + ACE_POSIX_Asynch_Transmit_File_Result (handler, + socket, + file, + header_and_trailer, + bytes_to_write, + offset, + offset_high, + bytes_per_send, + flags, + act, + event, + priority), + 0); + return implementation; +} + +ACE_POSIX_Proactor::ACE_POSIX_Proactor (void) +{ +} + +void +ACE_POSIX_Proactor::application_specific_code (ACE_POSIX_Asynch_Result *asynch_result, + u_long bytes_transferred, + int success, + const void *completion_key, + u_long error) +{ + ACE_SEH_TRY + { + // Call completion hook + asynch_result->complete (bytes_transferred, + success, + (void *) completion_key, + error); + } + ACE_SEH_FINALLY + { + // This is crucial to prevent memory leaks + delete asynch_result; + } +} + + + +int +ACE_POSIX_Proactor::wake_up_dispatch_threads (void) +{ + return 0; +} + +int +ACE_POSIX_Proactor::close_dispatch_threads (int) +{ + return 0; +} + +size_t +ACE_POSIX_Proactor::number_of_threads (void) const +{ + // @@ Implement it. + return 0; +} + +void +ACE_POSIX_Proactor::number_of_threads (size_t threads) +{ + // @@ Implement it. + ACE_UNUSED_ARG (threads); +} + +#if 0 +ACE_Proactor::Timer_Queue * +ACE_POSIX_Proactor::timer_queue (void) const +{ + return this->timer_queue_; +} + +void +ACE_POSIX_Proactor::timer_queue (Timer_Queue *tq) +{ + // cleanup old timer queue + if (this->delete_timer_queue_) + { + delete this->timer_queue_; + this->delete_timer_queue_ = 0; + } + + // new timer queue + if (tq == 0) + { + this->timer_queue_ = new Timer_Heap; + this->delete_timer_queue_ = 1; + } + else + { + this->timer_queue_ = tq; + this->delete_timer_queue_ = 0; + } + + // Set the proactor in the timer queue's functor + this->timer_queue_->upcall_functor ().proactor (*this); +} +#endif /* 0 */ + +// ********************************************************************* + +class ACE_Export ACE_AIO_Accept_Handler : public ACE_Handler +{ + // = TITLE + // Helper class for doing Asynch_Accept in POSIX4 systems, in + // the case of doing AIO_CONTROL_BLOCKS strategy. + // + // = DESCRIPTION + // Doing Asynch_Accept in POSIX4 implementation is tricky. In + // the case of doing the things with AIO_CONTROL_BLOCKS and not + // with Real-Time Signals, this becomes even more trickier. We + // use a notifyn pipe here to implement Asynch_Accpet. This class + // will issue a <Asynch_Read> on the pipe. <Asynch_Accept> will + // send a result pointer containg all the information through + // this pipe. + // Handling the MessageBlock: + // We give this message block to read the result pointer through + // the notify pipe. We expect that to read 4 bytes from the + // notify pipe, for each <accept> call. Before giving this + // message block to another <accept>, we update <wr_ptr> and put + // it in its initial position. +public: + ACE_AIO_Accept_Handler (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor); + // Constructor. You need the posix proactor because you need to call + // things like application_specific_code etc. Having the main + // proactor is good so that life is easier when we use Asynch_Read, + // while issuing asynchronous read on the notify pipe. + + virtual ~ACE_AIO_Accept_Handler (void); + // Destructor. + +#if 0 + void proactor (ACE_Proactor *proactor); + // Set the Proactor pointer. POSIX_AIOCB_Proactor may not have the + // Proactor pointer when it creates this object and so we have this + // method so that it can set it when it gets it. +#endif /* 0 */ + + int notify (ACE_POSIX_Asynch_Accept_Result *result); + // Send this Result to Proactor through the notification pipe. + + virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result); + // Read from the pipe is complete. We get the <Result> from + // Asynch_Handler. We have to do the notification here. + +private: +#if 0 + ACE_Proactor *proactor_; + // The main proactor interface. +#endif /* 0 */ + + ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor_; + // The implementation proactor class. + + ACE_Message_Block message_block_; + // Message block to get ACE_Asynch_Accept::Result pointer from + // ACE_Asych_Accept. + + ACE_Pipe pipe_; + // Pipe for the communication between Proactor and the + // Asynch_Accept. + + ACE_POSIX_AIOCB_Asynch_Read_Stream read_stream_; + // To do asynch_read on the pipe. + + ACE_AIO_Accept_Handler (void); + // Default constructor. Shouldnt be called. +}; + +ACE_AIO_Accept_Handler::ACE_AIO_Accept_Handler (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor) + : posix_aiocb_proactor_ (posix_aiocb_proactor), + message_block_ (sizeof (ACE_POSIX_Asynch_Accept_Result *)), + read_stream_ (posix_aiocb_proactor) +{ + // Open the pipe. + this->pipe_.open (); + + // Open the read stream. + if (this->read_stream_.open (*this, + this->pipe_.read_handle (), + 0, // Completion Key + 0) // Proactor + == -1) + ACE_ERROR ((LM_ERROR, + "%N:%l:%p\n", + "Open on Read Stream failed")); + + // Issue an asynch_read on the read_stream of the notify pipe. + if (this->read_stream_.read (this->message_block_, + sizeof (ACE_POSIX_Asynch_Accept_Result *), + 0, // ACT + 0) // Priority + == -1) + ACE_ERROR ((LM_ERROR, + "%N:%l:%p\n", + "Read from stream failed")); +} + +ACE_AIO_Accept_Handler::~ACE_AIO_Accept_Handler (void) +{ +} + +int +ACE_AIO_Accept_Handler::notify (ACE_POSIX_Asynch_Accept_Result *result) +{ + // Send the result pointer through the pipe. + int return_val = ACE::send (this->pipe_.write_handle (), + (char *) &result, + sizeof (result)); + if (return_val != sizeof (result)) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P %t):%p\n", + "Error:Writing on to pipe failed"), + -1); + return 0; +} + +void +ACE_AIO_Accept_Handler::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result) +{ + // @@ + ACE_DEBUG ((LM_DEBUG, "ACE_AIO_Accept_Handler::handle_read_stream called\n")); + + // The message block actually contains the ACE_POSIX_Asynch_Accept_Result + // pointer. + ACE_POSIX_Asynch_Accept_Result *accept_result = 0; + accept_result = *(ACE_POSIX_Asynch_Accept_Result **) result.message_block ().rd_ptr (); + + // Do the upcall. + this->posix_aiocb_proactor_->application_specific_code (accept_result, + 0, // No Bytes transferred. + 1, // Success. + 0, // Completion token. + 0); // Error. + + // Set the message block properly. Put the <wr_ptr> back in the + // initial position. + if (this->message_block_.length () > 0) + this->message_block_.wr_ptr (this->message_block_.rd_ptr ()); + + // One accept has completed. Issue a read to handle any <accept>s in + // the future. + if (this->read_stream_.read (this->message_block_, + sizeof (ACE_POSIX_Asynch_Accept_Result), + 0, // ACT + 0) // Priority + == -1) + ACE_ERROR ((LM_ERROR, + "%N:%l:%p\n", + "Read from stream failed")); +} + +// ********************************************************************* + +ACE_POSIX_AIOCB_Proactor::ACE_POSIX_AIOCB_Proactor (void) + : aio_accept_handler_ (0), + aiocb_list_max_size_ (ACE_RTSIG_MAX), + aiocb_list_cur_size_ (0) +{ + // Initialize the array. + for (size_t ai = 0; ai < this->aiocb_list_max_size_; ai++) + aiocb_list_[ai] = 0; + + // Accept Handler for aio_accept. Remember! this issues a Asynch_Read + // on the notify pipe for doing the Asynch_Accept. + ACE_NEW (aio_accept_handler_, + ACE_AIO_Accept_Handler (this)); +} + +// Destructor. +ACE_POSIX_AIOCB_Proactor::~ACE_POSIX_AIOCB_Proactor (void) +{ +} + +int +ACE_POSIX_AIOCB_Proactor::handle_events (ACE_Time_Value &wait_time) +{ + // Decrement <wait_time> with the amount of time spent in the method + ACE_Countdown_Time countdown (&wait_time); + return this->handle_events (wait_time.msec ()); +} + +int +ACE_POSIX_AIOCB_Proactor::handle_events (void) +{ + return this->handle_events (ACE_INFINITE); +} + +ACE_Asynch_Read_Stream_Impl * +ACE_POSIX_AIOCB_Proactor::create_asynch_read_stream (void) +{ + ACE_Asynch_Read_Stream_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, + ACE_POSIX_AIOCB_Asynch_Read_Stream (this), + 0); + return implementation; +} + +ACE_Asynch_Write_Stream_Impl * +ACE_POSIX_AIOCB_Proactor::create_asynch_write_stream (void) +{ + ACE_Asynch_Write_Stream_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, + ACE_POSIX_AIOCB_Asynch_Write_Stream (this), + 0); + return implementation; +} + +ACE_Asynch_Read_File_Impl * +ACE_POSIX_AIOCB_Proactor::create_asynch_read_file (void) +{ + ACE_Asynch_Read_File_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, + ACE_POSIX_AIOCB_Asynch_Read_File (this), + 0); + return implementation; +} + +ACE_Asynch_Write_File_Impl * +ACE_POSIX_AIOCB_Proactor::create_asynch_write_file (void) +{ + ACE_Asynch_Write_File_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, + ACE_POSIX_AIOCB_Asynch_Write_File (this), + 0); + return implementation; +} + +ACE_Asynch_Accept_Impl * +ACE_POSIX_AIOCB_Proactor::create_asynch_accept (void) +{ + ACE_Asynch_Accept_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, + ACE_POSIX_AIOCB_Asynch_Accept (this), + 0); + return implementation; +} + +ACE_Asynch_Transmit_File_Impl * +ACE_POSIX_AIOCB_Proactor::create_asynch_transmit_file (void) +{ + ACE_Asynch_Transmit_File_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, + ACE_POSIX_AIOCB_Asynch_Transmit_File (this), + 0); + return implementation; +} + +int +ACE_POSIX_AIOCB_Proactor::notify_asynch_accept (ACE_POSIX_Asynch_Accept_Result* result) +{ + this->aio_accept_handler_->notify (result); + + return 0; +} + +int +ACE_POSIX_AIOCB_Proactor::handle_events (unsigned long milli_seconds) +{ + if (this->aiocb_list_cur_size_ == 0) + // No aio is pending. + return 0; + + // Wait for asynch operation to complete. + // @@ Assing milli seconds correctly. + timespec timeout; + timeout.tv_sec = milli_seconds; + timeout.tv_nsec = 0; + + if (aio_suspend (this->aiocb_list_, + this->aiocb_list_max_size_, + &timeout) == -1) + { + // If failure is coz of timeout, then return *0* but set errno + // appropriately. This is what the WinNT proactor does. + if (errno == EAGAIN) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p\n", + "aio_suspend"), + 0); + else + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p\n", + "aio_suspend"), + -1); + } + + // Check which aio has finished. + size_t ai; + int error_status = 0; + int return_status = 0; + for (ai = 0; ai < this->aiocb_list_max_size_; ai++) + { + if (aiocb_list_ [ai] == 0) + continue; + + // Analyze error and return values. + + // Get the error status of the aio_ operation. + error_status = aio_error (aiocb_list_[ai]); + if (error_status == -1) + // <aio_error> itself has failed. + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p\n", + "<aio_error> has failed"), + -1); + + if (error_status == EINPROGRESS) + // <aio_> operation is still in progress. + continue; + + // Error_status is not -1 and not EINPROGRESS. So, an <aio_> + // operation has finished (successfully or unsuccessfully!!!) + + ACE_ERROR ((LM_ERROR, + "%N:%l:error_status = %d\n", + error_status)); + + // Get the return_status of the <aio_> operation. + return_status = aio_return (aiocb_list_[ai]); + if (return_status == -1) + { + // <aio_return> itself has failed. + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p\n", + "<aio_return> failed"), + -1); + } + else + { + ACE_DEBUG ((LM_DEBUG, "An aio has finished\n")); + break; + } + } + + if (ai == this->aiocb_list_max_size_) + // Nothing completed. + return 0; + + // Retrive the result pointer. + ACE_POSIX_Asynch_Result *asynch_result = + // dynamic_cast <ACE_POSIX_Asynch_Result *> (this->aiocb_list_[ai]); + (ACE_POSIX_Asynch_Result *) (this->aiocb_list_[ai]); + if (asynch_result == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%N:%l:%p\n", + "Dynamic cast failed"), + -1); + + // Invalidate entry in the aiocb list. + this->aiocb_list_[ai] = 0; + this->aiocb_list_cur_size_--; + + // Call the application code. + // @@ Pass <errno> instead of 0. Check out on LynxOS. It is set + // to 77 somewhere. + this->application_specific_code (asynch_result, + return_status, // Bytes transferred. + 1, // Success + 0, // No completion key. + error_status); // Error + + return 0; +} + +void +ACE_POSIX_AIOCB_Proactor::application_specific_code (ACE_POSIX_Asynch_Result *asynch_result, + u_long bytes_transferred, + int success, + const void *completion_key, + u_long error) +{ + ACE_POSIX_Proactor::application_specific_code (asynch_result, + bytes_transferred, + success, + completion_key, + error); +} + +int +ACE_POSIX_AIOCB_Proactor::register_aio_with_proactor (aiocb *aiocb_ptr) +{ + if (aiocb_ptr == 0) + { + ACE_DEBUG ((LM_DEBUG, + "Status check max %d cur %d\n", + this->aiocb_list_max_size_, + this->aiocb_list_cur_size_)); + + // Just check the status of the list. + if (this->aiocb_list_cur_size_ >= + this->aiocb_list_max_size_) + return -1; + else + return 0; + } + + // Non-zero ptr. Find a free slot and store. + + // Make sure again. + if (this->aiocb_list_cur_size_ >= + this->aiocb_list_max_size_) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:Asynch_Operation: No space to store the <aio> info.\n"), + -1); + + // Slot(s) available. Find a free one. + size_t ai; + for (ai = 0; + ai < this->aiocb_list_max_size_; + ai++) + if (this->aiocb_list_[ai] == 0) + break; + + // Sanity check. + if (ai == this->aiocb_list_max_size_) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:Asynch_Operation: No space to store the <aio> info.\n"), + -1); + + // Store the pointers. + this->aiocb_list_[ai] = aiocb_ptr; + this->aiocb_list_cur_size_ ++; + + return 0; +} + +// ********************************************************************* + +ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor (void) +{ + // Make the sigset_t consisting of the completion signals. + if (sigemptyset (&this->RT_completion_signals_) < 0) + ACE_ERROR ((LM_ERROR, + "Error:%p\n", + "Couldn't init the RT completion signal set")); + + if (sigaddset (&this->RT_completion_signals_, ACE_SIG_AIO) < 0) + ACE_ERROR ((LM_ERROR, + "Error:%p\n", + "Couldnt init the RT completion signal set")); + + // Mask them. + if (sigprocmask (SIG_BLOCK, &RT_completion_signals_, 0) < 0) + ACE_ERROR ((LM_ERROR, + "Error:%p\n", + "Couldnt mask the RT completion signals")); + + // Setting up the handler(actually Null handler) for these signals. + struct sigaction reaction; + sigemptyset (&reaction.sa_mask); // Nothing else to mask. + reaction.sa_flags = SA_SIGINFO; // Realtime flag. +#if defined (SA_SIGACTION) + // Lynx says, it is better to set this bit to be portable. + reaction.sa_flags &= SA_SIGACTION; +#endif /* SA_SIGACTION */ + reaction.sa_sigaction = 0; // No handler. + int sigaction_return = sigaction (ACE_SIG_AIO, + &reaction, + 0); + if (sigaction_return == -1) + ACE_ERROR ((LM_ERROR, + "Error:%p\n", + "Proactor couldnt do sigaction for the RT SIGNAL")); +} + + +ACE_POSIX_SIG_Proactor::~ACE_POSIX_SIG_Proactor (void) +{ + // @@ Enable the masked signals again. +} + +int +ACE_POSIX_SIG_Proactor::handle_events (ACE_Time_Value &wait_time) +{ + // Decrement <wait_time> with the amount of time spent in the method + ACE_Countdown_Time countdown (&wait_time); + return this->handle_events (wait_time.msec ()); +} + +int +ACE_POSIX_SIG_Proactor::handle_events (void) +{ + return this->handle_events (ACE_INFINITE); +} + +ACE_Asynch_Read_Stream_Impl * +ACE_POSIX_SIG_Proactor::create_asynch_read_stream (void) +{ + ACE_Asynch_Read_Stream_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, ACE_POSIX_SIG_Asynch_Read_Stream (this), 0); + return implementation; +} + +ACE_Asynch_Write_Stream_Impl * +ACE_POSIX_SIG_Proactor::create_asynch_write_stream (void) +{ + ACE_Asynch_Write_Stream_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, ACE_POSIX_SIG_Asynch_Write_Stream (this), 0); + return implementation; +} + +ACE_Asynch_Read_File_Impl * +ACE_POSIX_SIG_Proactor::create_asynch_read_file (void) +{ + ACE_Asynch_Read_File_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, ACE_POSIX_SIG_Asynch_Read_File (this), 0); + return implementation; +} + +ACE_Asynch_Write_File_Impl * +ACE_POSIX_SIG_Proactor::create_asynch_write_file (void) +{ + ACE_Asynch_Write_File_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, ACE_POSIX_SIG_Asynch_Write_File (this), 0); + return implementation; +} + +ACE_Asynch_Accept_Impl * +ACE_POSIX_SIG_Proactor::create_asynch_accept (void) +{ + ACE_Asynch_Accept_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, ACE_POSIX_SIG_Asynch_Accept (this), 0); + return implementation; +} + +ACE_Asynch_Transmit_File_Impl * +ACE_POSIX_SIG_Proactor::create_asynch_transmit_file (void) +{ + ACE_Asynch_Transmit_File_Impl *implementation = 0; + ACE_NEW_RETURN (implementation, + ACE_POSIX_SIG_Asynch_Transmit_File (this), + 0); + return implementation; +} + +int +ACE_POSIX_SIG_Proactor::handle_events (unsigned long milli_seconds) +{ + // Wait for <milli_seconds> amount of time. + // @@ Assigning <milli_seconds> to tv_sec. + timespec timeout; + timeout.tv_sec = milli_seconds; + timeout.tv_nsec = 0; + + // To get back the signal info. + siginfo_t sig_info; + + // Await the RT completion signal. + int sig_return = sigtimedwait (&this->RT_completion_signals_, + &sig_info, + &timeout); + + // Error case. + // If failure is coz of timeout, then return *0* but set + // errno appropriately. This is what the WinNT proactor + // does. + if (sig_return == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p\n", + "Waiting for RT completion signals"), + 0); + + // RT completion signals returned. + if (sig_return != ACE_SIG_AIO) + ACE_ERROR_RETURN ((LM_ERROR, + "Unexpected signal (%d) has been received while waiting for RT Completion Signals\n", + sig_return), + -1); + + // @@ Debugging. + ACE_DEBUG ((LM_DEBUG, + "Sig number found in the sig_info block : %d\n", + sig_info.si_signo)); + + // Is the signo returned consistent? + if (sig_info.si_signo != sig_return) + ACE_ERROR_RETURN ((LM_ERROR, + "Inconsistent signal number (%d) in the signal info block\n", + sig_info.si_signo), + -1); + + // @@ Debugging. + ACE_DEBUG ((LM_DEBUG, + "Signal code for this signal delivery : %d\n", + sig_info.si_code)); + + // Retrive the result pointer. + ACE_POSIX_Asynch_Result *asynch_result = + (ACE_POSIX_Asynch_Result *) sig_info.si_value.sival_ptr; + + // Check the <signal code> and act according to that. + if (sig_info.si_code == SI_ASYNCIO) + { + // Retrieve the aiocb from Result ptr. + // @@ Some checking should be done to make sure this pointer + // is valid. Otherwise <aio_error> will bomb. + aiocb* aiocb_ptr = + (aiocb *)asynch_result; + + // Analyze error and return values. Return values are + // actually <errno>'s associated with the <aio_> call + // corresponding to aiocb_ptr. + int error_status = aio_error (aiocb_ptr); + if (error_status == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p\n", + "Invalid control block was sent to <aio_error> for compleion querying"), + -1); + + // Completion signal has been received, so it can't be in + // progress. + // ACE_ASSERT (error_status != EINPROGRESS) + + // No error occured in the AIO operation. + int return_status = aio_return (aiocb_ptr); + if (return_status == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p\n", + "Invalid control block was send to <aio_return>"), + -1); + } + else + { + ACE_DEBUG ((LM_DEBUG, "An aio has finished\n")); + + this->application_specific_code (asynch_result, + return_status, + 1, // Result : True. + 0, // No completion_signal. + error_status); // Error. + } + } + else if (sig_info.si_code == SI_QUEUE) + { + // @@ Just debugging. + ACE_DEBUG ((LM_DEBUG, "<sigqueue>'d signal received\n")); + + this->application_specific_code (asynch_result, + 0, // No bytes transferred. + 1, // Result : True. + 0, // No completion key. + 0); // No error. + } + else + // Unknown signal code. + ACE_ERROR_RETURN ((LM_DEBUG, + "Unexpected signal code (%d) returned on completion querying\n", + sig_info.si_code), + -1); + + return 0; +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +#if 0 +template class ACE_Timer_Queue_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, + ACE_SYNCH_RECURSIVE_MUTEX>; +template class ACE_Timer_Queue_Iterator_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, + ACE_SYNCH_RECURSIVE_MUTEX>; +template class ACE_Timer_List_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, + ACE_SYNCH_RECURSIVE_MUTEX>; +template class ACE_Timer_List_Iterator_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, + ACE_SYNCH_RECURSIVE_MUTEX>; +template class ACE_Timer_Node_T<ACE_Handler *>; +template class ACE_Unbounded_Set<ACE_Timer_Node_T<ACE_Handler *> *>; +template class ACE_Unbounded_Set_Iterator<ACE_Timer_Node_T<ACE_Handler *> *>; +template class ACE_Node <ACE_Timer_Node_T<ACE_Handler *> *>; +template class ACE_Free_List<ACE_Timer_Node_T<ACE_Handler *> >; +template class ACE_Locked_Free_List<ACE_Timer_Node_T<ACE_Handler *>, ACE_Null_Mutex>; +template class ACE_Timer_Heap_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, + ACE_SYNCH_RECURSIVE_MUTEX>; +template class ACE_Timer_Heap_Iterator_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, + ACE_SYNCH_RECURSIVE_MUTEX>; +template class ACE_Timer_Wheel_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, + ACE_SYNCH_RECURSIVE_MUTEX>; +template class ACE_Timer_Wheel_Iterator_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, + ACE_SYNCH_RECURSIVE_MUTEX>; +#endif /* 0 */ +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Timer_Queue_T<ACE_Handler *,\ + ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> +#pragma instantiate ACE_Timer_Queue_Iterator_T<ACE_Handler *,\ + ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> +#pragma instantiate ACE_Timer_List_T<ACE_Handler *,\ + ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> +#pragma instantiate ACE_Timer_List_Iterator_T<ACE_Handler *,\ + ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> +#pragma instantiate ACE_Timer_Heap_T<ACE_Handler *,\ + ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> +#pragma instantiate ACE_Timer_Heap_Iterator_T<ACE_Handler *,\ + ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> +#pragma instantiate ACE_Timer_Wheel_T<ACE_Handler *, + ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> +#pragma instantiate ACE_Timer_Wheel_Iterator_T<ACE_Handler *,\ + ACE_Proactor_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +#endif /* ACE_HAS_AIO_CALLS */ diff --git a/ace/WIN32_Proactor.i b/ace/WIN32_Proactor.i new file mode 100644 index 00000000000..6318deb79a0 --- /dev/null +++ b/ace/WIN32_Proactor.i @@ -0,0 +1,2 @@ +/* -*- C++ -*- */ +// $Id$ |