[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.
|