[asycxx-devel] SF.net SVN: asycxx:[26] trunk
Status: Alpha
Brought to you by:
joe_steeve
From: <joe...@us...> - 2009-04-08 07:30:41
|
Revision: 26 http://asycxx.svn.sourceforge.net/asycxx/?rev=26&view=rev Author: joe_steeve Date: 2009-04-08 07:30:35 +0000 (Wed, 08 Apr 2009) Log Message: ----------- all Transports are now 'Selectable's This makes sure we can add the Transport directly to the Reactor instead of having callbacks between them. From: Joe Steeve <js...@hi...> Modified Paths: -------------- trunk/include/asycxx/Transport.h trunk/src/Transport.cxx Modified: trunk/include/asycxx/Transport.h =================================================================== --- trunk/include/asycxx/Transport.h 2009-04-08 07:29:52 UTC (rev 25) +++ trunk/include/asycxx/Transport.h 2009-04-08 07:30:35 UTC (rev 26) @@ -14,66 +14,109 @@ #ifndef __HIPRO_ASYCXX__TRANSPORT_H__ #define __HIPRO_ASYCXX__TRANSPORT_H__ +#include <list> -#include <deque> - #include "Error.h" #include "Reactor.h" #include "DataBuffer.h" +#include "Selectable.h" -class Protocol; - -#define ASYCXX_TRANSPORT_DEFAULT_READ_BUFSIZE 1024 -class Transport +namespace asycxx { + class Protocol; -public: - Transport (Reactor *reactor, int fd); - virtual ~Transport (); + class Transport : public Selectable + { + public: + /** + * \brief CTOR + * + * \param[in] reactor Pointer to a Reactor + * \param[in] fd A valid file-descriptor to build the transport on + */ + Transport (Reactor *reactor, int fd); + virtual ~Transport (); - /* method to write to the transport */ - void Write (DataBuffer *data); - /* method to disconnect the transport and mark for destruction */ - void LoseConnection (void); + /** + * \brief Sets the transport ready for reading + */ + void startReading (void); - /* methods to configure the transport */ - void configureReadTimeout (h_msecs_t timeout); - void configureWriteTimeout (h_msecs_t timeout); - void configureReadBufferSize (size_t len); + /** + * \brief Sets the transport to stop reading + */ + void stopReading (void); - /* accessors */ - int FD (void) { return m_Fd; } - Protocol * GetProtocol (void); - void SetProtocol (Protocol *protocol); - -protected: - Reactor *m_Reactor; - Protocol *m_Protocol; - int m_Fd; + /** + * \brief Sets the transport ready for writing + */ + void startWriting (void); - size_t m_readBufSize; - h_msecs_t m_writeTimeout; /* the timeout used for reading */ - Deferred *m_readDefer; /* deferred to handle reading */ - Deferred *m_writeDefer; /* deferred to handle writing */ - std::deque<DataBuffer *> m_writeBuffers; - bool m_bDisconnectAndDie; + /** + * \brief Sets the transport to stop writing + */ + void stopWriting (void); - /* methods to be implemented by the derived sub-classes */ - virtual Result doWrite (void) = 0; - virtual Result doRead (DataBuffer *data) = 0; - virtual void doDisconnect (void) = 0; + /** + * \brief Attach the given protocol to the Transport + */ + Protocol * getProtocol (void) { return m_Protocol; } - /* handler methods */ - static void handleReadable (void *obj); - static void handleReadTimeout (void *obj, h_msecs_t excess_time); - static void handleWritable (void *obj); - static void handleWriteTimeout (void *obj, h_msecs_t excess_time); + /** + * \brief Get the currently attached protocol + */ + void setProtocol (Protocol *protocol); -private: - void KillMeIfYouMust (void); + /** + * \brief Get the reactor to which the Transport is hooked to + */ + Reactor * getReactor (void) { return m_Reactor; } -}; + /** + * \brief Query whether the 'read end' is open + */ + bool isReaderOpen (void) { return m_bReaderOpen; } + /** + * \brief Query whether the 'write end' is open + */ + bool isWriterOpen (void) { return m_bWriterOpen; } + + /** + * \brief Close the transport completely + */ + virtual void Close (void) = 0; + + /** + * \brief close the read-end of the transport + */ + virtual void closeReader (void) = 0; + + /** + * \brief close the write-end of the transport + */ + virtual void closeWriter (void) = 0; + + protected: + /** + * \brief Mark that the reader has been closed + */ + void markReaderAsClosed (void) { m_bReaderOpen = false; } + + /** + * \brief Mark that the writer has been closed + */ + void markWriterAsClosed (void) { m_bWriterOpen = false; } + + private: + Reactor *m_Reactor; + Protocol *m_Protocol; + bool m_bAddedToReaders; + bool m_bAddedToWriters; + bool m_bReaderOpen; + bool m_bWriterOpen; + }; +} #endif /* __HIPRO_ASYCXX__TRANSPORT_H__ */ /* Modified: trunk/src/Transport.cxx =================================================================== --- trunk/src/Transport.cxx 2009-04-08 07:29:52 UTC (rev 25) +++ trunk/src/Transport.cxx 2009-04-08 07:30:35 UTC (rev 26) @@ -22,333 +22,91 @@ #include <asycxx/Transport.h> #include <asycxx/Protocol.h> -/** - * \brief ctor - * - * \param[in] reactor Pointer to a Reactor - * \param[in] fd A valid file-descriptor to build the transport on + +using namespace asycxx; + + +/* + * CTOR */ Transport::Transport (Reactor *reactor, int fd) { ASSERT ((reactor != NULL), "cannot marry a <NULL> Reactor"); ASSERT ((fd != -1), "bad file-descriptor. checking parameters"); - m_Reactor = reactor; - m_Fd = fd; - m_bDisconnectAndDie = false; - /* set file-descriptor as non-blocking */ - SetFDAsNonBlocking (m_Fd); + /* initialize */ + m_bAddedToReaders = false; + m_bAddedToWriters = false; - /* default configuration */ - m_readDefer = NULL; - m_writeDefer = NULL; - configureReadTimeout (0L); - configureWriteTimeout (0L); - configureReadBufferSize (ASYCXX_TRANSPORT_DEFAULT_READ_BUFSIZE); + m_bReaderOpen = true; + m_bWriterOpen = true; + + m_Reactor = reactor; + m_Protocol = NULL; + + /* set file-descriptor as non-blocking */ + SetFDAsNonBlocking (fd); + Fd (fd); } -/** - * \brief dtor - */ +/* DTOR */ Transport::~Transport () { - DataBuffer *data; - - /* discard the DataBuffers in the pending queue */ - while (m_writeBuffers.size() > 0) - { - data = m_writeBuffers[0]; - ERR ("Transport<%p> dumping write-buffer <%p>, len=%d", - this, data->Data(), data->Len()); - m_writeBuffers.pop_front(); - data->DisOwn(); - } - /* un-register from the reactor */ - if (m_readDefer != NULL) - { - m_Reactor->UnRegister (m_readDefer); - } - if (m_writeDefer != NULL) - { - m_Reactor->UnRegister (m_writeDefer); - } + stopReading(); + stopWriting(); - /* destroy the protocol */ - if (m_Protocol != NULL) - { - delete m_Protocol; - } - - /* we own the fd that was given to us */ - close (m_Fd); + /* destroy the protocol. we own it. */ + if (m_Protocol != NULL) { delete m_Protocol; } } -/* accessors for protocol */ -void -Transport::SetProtocol (Protocol *protocol) -{ - ASSERT ((protocol != NULL), "checking parameters"); - m_Protocol = protocol; -} - - -Protocol * -Transport::GetProtocol (void) -{ - ASSERT ((m_Protocol != NULL), "protocol not set."); - return m_Protocol; -} - - -/** - * \brief Configures the reading timeout - * - * \param[in] timeout timeout in milli-seconds - * - * \details This method sets a timeout for the reading. - */ -void -Transport::configureReadTimeout (h_msecs_t timeout) -{ - if (m_readDefer != NULL) +/* Methods to add/remove the transport from the readers/writers list + * of the reactor */ +void Transport::startReading (void) +{ + if (m_bAddedToReaders == false) { - m_Reactor->UnRegister (m_readDefer); + m_Reactor->addReader(this); + m_bAddedToReaders = true; } - if (timeout > 0L) - { - m_readDefer = m_Reactor->OnReadable (m_Fd, timeout); - m_readDefer->OnTimeout (Transport::handleReadTimeout, this); - } - else - { - m_readDefer = m_Reactor->OnReadable (m_Fd); - } - m_readDefer->OnEvent (Transport::handleReadable, this); } - -/** - * \brief Configures the writing timeout - * - * \param[in] timeout timeout in milli-seconds - * - * \details This method sets a timeout for the writing. This timeout - * becomes effective from the next write operation - */ -void -Transport::configureWriteTimeout (h_msecs_t timeout) -{ - m_writeTimeout = timeout; -} - - -/** - * \brief Configures the size of the read-buffer - * - * \param[in] len Number of bytes to set the read-buffer to - * - * \details This method sets the read-buffer to the given length. The - * read-buffer-len is the maximum amount of data that can be read from - * the transport at any time. The transport does not wait till the - * buffer of read-buffer-len is full. When data is available, utmost - * read-buffer-len bytes can be read from it. If more data is still - * available, they'll be read only in the next read operation. - */ -void -Transport::configureReadBufferSize (size_t len) -{ - ASSERT ((len != 0), "zero length read-buffer??"); - m_readBufSize = len; -} - - -/** - * \brief Queues the provided data-buffer for writing - * - * \param[in] data The DataBuffer object that should be written - * - * \details This method queues the given DataBuffer to the - * m_writeBuffers queue. This queue is flushed out when the - * file-descriptor becomes writable next. This class assumes ownership - * of the provided DataBuffer. - */ -void -Transport::Write (DataBuffer *data) -{ - ASSERT ((m_Protocol != NULL), "no protocol attached"); - ASSERT ((data != NULL), "given data-buffer is NULL"); - - /* If we are not listening for write-events already, then hook up - with the reactor for writable events */ - if (m_writeDefer == NULL) +void Transport::stopReading (void) +{ + if (m_bAddedToReaders == true) { - if (m_writeTimeout == 0L) - { - m_writeDefer = m_Reactor->OnWritable (m_Fd); - } - else - { - m_writeDefer = m_Reactor->OnWritable (m_Fd, m_writeTimeout); - m_writeDefer->OnTimeout (Transport::handleWriteTimeout, this); - } - m_writeDefer->OnEvent (Transport::handleWritable, this); + m_Reactor->removeReader(this); + m_bAddedToReaders = false; } - /* add the DataBuffer to the queue */ - m_writeBuffers.push_back (data); - - /* assume ownership of the given data-buffer. we do this last so - that any exception in the middle does not cause a leak */ - data->Own (); } - -/** - * \brief Mark the connection to be destroyed. - * - * \details This method marks the transport for destruction. This - * should be used by the protocol to notify the transport to destory - * itself. The Transport will do the destruction once it regains - * control from the event handlers that it has called. - */ -void -Transport::LoseConnection (void) -{ - ASSERT ((m_Protocol != NULL), "no protocol attached"); - m_bDisconnectAndDie = true; -} - - -/* handlers for reactor generated events */ - -/** \todo: should use ioctl(m_Fd, SIOCINQ) to find the amount of - unread data in the socket and then construct the DataBuffer. This - should be done in the 'doRead' coz, Transport does not know what - kind of file-descriptor we have with us. */ -void -Transport::handleReadable (void *obj) -{ - ASSERT ((obj != NULL), "checking parameters"); - - DataBuffer *data; - Result ret; - Transport *trans = (Transport *) obj; - ASSERT ((trans->m_Protocol != NULL), "no protocol attached"); - - /* Read till there is no more */ - while (1) +void Transport::startWriting (void) +{ + if (m_bAddedToWriters == false) { - data = new DataBuffer (trans->m_readBufSize); - - /* call the sub-classes read-method to fill up the - data-buffer */ - ret = trans->doRead (data); - if (ret != Result_Success) - { - /* reading from transport failed */ - data->DisOwn (); - trans->m_Protocol->ReadError (); - goto __handlelReadable__ScreamAndDie__; - } - - if (data->Len() == 0) - { - /* If there is no more to read, then get out */ - data->DisOwn (); - break; - } - - /* give data-buffer to the protocol. after this point, the - Protocol takes responsibility for the data-buffer object */ - trans->m_Protocol->DataAvailable (data); - data->DisOwn (); - - /* check whether we should die */ - if (trans->m_bDisconnectAndDie == true) - { - goto __handlelReadable__ScreamAndDie__; - } + m_Reactor->addWriter(this); + m_bAddedToWriters = true; } - return; - - __handlelReadable__ScreamAndDie__ : - trans->doDisconnect (); - trans->m_Protocol->ConnectionLost (); - delete trans; - return; } - -void -Transport::handleReadTimeout (void *obj, h_msecs_t excess_time) -{ - ASSERT ((obj != NULL), "checking parameters"); - Transport *trans = (Transport *) obj; - ASSERT ((trans->m_Protocol != NULL), "no protocol attached"); - - /* notify read-timeout to the protocol */ - trans->m_Protocol->ReadTimeout (excess_time); - - if (trans->m_bDisconnectAndDie == true) +void Transport::stopWriting (void) +{ + if (m_bAddedToWriters == true) { - goto __handlelReadTimeout__ScreamAndDie__; + m_Reactor->removeWriter(this); + m_bAddedToWriters = false; } - - __handlelReadTimeout__ScreamAndDie__: - trans->doDisconnect (); - trans->m_Protocol->ConnectionLost (); - delete trans; - return; } - -void -Transport::handleWritable (void *obj) +void Transport::setProtocol (Protocol *protocol) { - ASSERT ((obj != NULL), "checking parameters"); - - Transport *trans = (Transport *) obj; - ASSERT ((trans->m_Protocol != NULL), "no protocol attached"); - - /* call the base-class method to write the pending buffers */ - Result ret; - ret = trans->doWrite (); - if (ret == Result_Error) - { - /* writing to transport failed */ - trans->m_Protocol->WriteError (); - goto __handlelWritable__ScreamAndDie__; - } - if (ret == Result_Success) - { - /* nothing more to write */ - trans->m_Reactor->UnRegister (trans->m_writeDefer); - trans->m_writeDefer = NULL; - } - return; - - __handlelWritable__ScreamAndDie__ : - trans->doDisconnect (); - trans->m_Protocol->ConnectionLost (); - delete trans; - return; + ASSERT ((protocol != NULL), "checking parameters"); + m_Protocol = protocol; } -void -Transport::handleWriteTimeout (void *obj, h_msecs_t excess_time) -{ - ASSERT ((obj != NULL), "checking parameters"); - - Transport *trans = (Transport *) obj; - ASSERT ((trans->m_Protocol != NULL), "no protocol attached"); - - /* notify write-timeout to the protocol */ - trans->m_Protocol->WriteTimeout (excess_time); -} - /* Local Variables: mode: c++ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |