#ifndef __JNET__JSOCKETNONBLOCKINGIO__ #define __JNET__JSOCKETNONBLOCKINGIO__ #include "JNet/JTCPSocket.hh" #include "JNet/JSocketStatus.hh" /** * \author mdejong */ namespace JNET {} namespace JPP { using namespace JNET; } namespace JNET { /** * Auxiliary class for non-blocking socket I/O. */ template class JSocketBuffer : public JSocketStatus { protected: /** * Default constructor. */ JSocketBuffer() : JSocketStatus(), __data(NULL), __size(0) {} public: /** * Constructor. * * \param buffer I/O data * \param length number of bytes */ JSocketBuffer(JElement_t* buffer, const int length) : JSocketStatus(), __data(buffer), __size(length) {} /** * Get size of pending data. * * \return number of bytes */ int getSize() const { return __size; } /** * Initialise buffer. * * \param buffer buffer */ void set(const JSocketBuffer& buffer) { set(buffer.__data, buffer.__size); } /** * Initialise buffer. * * \param buffer I/O data * \param length number of bytes */ void set(JElement_t* buffer, const int length) { if (status == IO_BUSY) { THROW(JSocketException, "Set socket buffer I/O while busy."); } status = (length != 0 ? IO_BUSY : IO_READY); counter = 0; __data = buffer; __size = length; } /** * Reset */ void reset() { JSocketStatus::reset(); __data = NULL; __size = 0; } protected: JElement_t* __data; int __size; }; typedef JSocketBuffer JSocketInputBuffer; typedef JSocketBuffer JSocketOutputBuffer; /** * Non-blocking socket reader. * This class can be used in case of non-blocking I/O * (see method JSocket::setNonBlocking()). */ class JSocketNonblockingReader : public JTCPSocket, public JSocketInputBuffer { public: /** * Constructor. * * \param socket socket */ JSocketNonblockingReader(const JTCPSocket& socket) : JTCPSocket(socket), JSocketInputBuffer() {} /** * Continuation of non-blocking read method. * * \return status */ JStatus_t read() { if (status == IO_BUSY) { ++counter; const int pos = JSocket::read(__data, __size); __data += pos; __size -= pos; } else { THROW(JSocketException, "Calling socket non-blocking read() while not busy."); } if (__size == 0) { status = IO_READY; } return status; } private: using JSocket::read; }; /** * Non-blocking socket writer. * This class can be used in case of non-blocking I/O * (see method JSocket::setNonBlocking()). */ class JSocketNonblockingWriter : public JTCPSocket, public JSocketOutputBuffer { public: /** * Constructor. * * \param socket socket */ JSocketNonblockingWriter(const JTCPSocket& socket) : JTCPSocket(socket), JSocketOutputBuffer() {} /** * Continuation of non-blocking write method. * * \return status */ JStatus_t write() { if (status == IO_BUSY) { ++counter; const int pos = JSocket::write(__data, __size); __data += pos; __size -= pos; } else { THROW(JSocketException, "Calling socket non-blocking write() while not busy."); } if (__size == 0) { status = IO_READY; } return status; } private: using JSocket::write; }; } #endif