diff options
-rw-r--r-- | ace/IOStream.cpp | 21 | ||||
-rw-r--r-- | ace/IOStream.h | 7 | ||||
-rw-r--r-- | ace/IOStream_T.h | 4 | ||||
-rw-r--r-- | ace/IOStream_T.i | 20 | ||||
-rw-r--r-- | tests/IOStream_Test.cpp | 26 |
5 files changed, 71 insertions, 7 deletions
diff --git a/ace/IOStream.cpp b/ace/IOStream.cpp index 42187b95422..6b9286d9cea 100644 --- a/ace/IOStream.cpp +++ b/ace/IOStream.cpp @@ -392,6 +392,8 @@ ACE_Streambuf::flushbuf (void) int ACE_Streambuf::get_one_byte (void) { + this->timeout_ = 0; + // The recv function will return immediately if there is no data // waiting. So, we use recv_n to wait for exactly one byte to come // from the peer. Later, we can use recv to see if there is @@ -399,7 +401,11 @@ ACE_Streambuf::get_one_byte (void) // to block but I like this better.) if (this->recv_n (base (), 1, MSG_PEEK, recv_timeout_) != 1) - return EOF; + { + if (errno == ETIME) + this->timeout_ = 1; + return EOF; + } else return 1; } @@ -426,7 +432,11 @@ ACE_Streambuf::fillbuf (void) // error. if (bc < 0) - return EOF; + { + if (errno == ETIME) + this->timeout_ = 1; + return EOF; + } // Move the get pointer to reflect the number of bytes we just read. @@ -609,5 +619,12 @@ ACE_Streambuf::~ACE_Streambuf (void) delete [] this->pbase_saved_; } +u_char ACE_Streambuf::timeout (void) +{ + u_char rval = this->timeout_; + time->timeout_ = 0; + return rval; +} + #endif /* !ACE_LACKS_ACE_IOSTREAM */ #endif /* ACE_IOSTREAM_C */ diff --git a/ace/IOStream.h b/ace/IOStream.h index 228bb1c0079..34273880331 100644 --- a/ace/IOStream.h +++ b/ace/IOStream.h @@ -184,6 +184,10 @@ public: u_int streambuf_size (void); // Query the streambuf for the size of it's buffers. + u_char timeout (void); + // Did we take an error because of an IO operation timeout? + // Note: Invoking this resets the flag. + protected: ACE_Streambuf (u_int streambuf_size, int io_mode); @@ -227,6 +231,9 @@ protected: // This defines the size of the input and output buffers. It can be // set by the object constructor. + u_char timeout_; + // Did we take an error because of an IO operatio timeout? + ACE_Time_Value recv_timeout_value_; ACE_Time_Value *recv_timeout_; // We want to allow the user to provide Time_Value pointers to diff --git a/ace/IOStream_T.h b/ace/IOStream_T.h index a2de38d64de..a793f77479c 100644 --- a/ace/IOStream_T.h +++ b/ace/IOStream_T.h @@ -121,6 +121,10 @@ public: int eof (void) const; // Returns 1 if we're at the end of the <STREAM>, i.e., if the // connection has closed down or an error has occurred, else 0. + // Under the covers, eof() calls the streambuf's timeout() + // function which will reset the timeout flag. As a result, you + // should save the return of eof() and check it instead of calling + // eof() successively. #if defined (ACE_HAS_STRING_CLASS) virtual ACE_IOStream<STREAM> &operator>> (ACE_IOStream_String &v); diff --git a/ace/IOStream_T.i b/ace/IOStream_T.i index e97583cafc7..49ee5a19d28 100644 --- a/ace/IOStream_T.i +++ b/ace/IOStream_T.i @@ -43,11 +43,23 @@ ACE_Streambuf_T<STREAM>::get_handle (void) template <class STREAM> ACE_INLINE int ACE_IOStream<STREAM>::eof (void) const { +// char c; +// return ACE_OS::recv (this->get_handle (), +// &c, +// sizeof c, +// MSG_PEEK) <= 0; + // Get the timeout value of the streambuf + ACE_Time_Value * timeout = this->streambuf_->recv_timeout(0); + + // Reset the timeout value of the streambuf + (void)this->streambuf_->recv_timeout(timeout); + char c; - return ACE_OS::recv (this->get_handle (), - &c, - sizeof c, - MSG_PEEK) <= 0; + int rval = this->streambuf_->recv_n( &c, sizeof c, MSG_PEEK, timeout ); + + // If recv_n() didn't fail or failed because of timeout we're + // not at EOF. + return rval != -1 && ! this->streambuf_->timeout(); } diff --git a/tests/IOStream_Test.cpp b/tests/IOStream_Test.cpp index b760bf3e28e..c496e4e2a97 100644 --- a/tests/IOStream_Test.cpp +++ b/tests/IOStream_Test.cpp @@ -199,11 +199,31 @@ client (void *arg = 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) Client Receiving\n")); + ACE_Time_Value timeout (2); + ACE_Time_Value *timeoutp = &timeout; + + server >> timeoutp; + int i; float f1, f2; long l; double d; - server >> i; + + while( !(server >> i) ) + { + int eof = server.eof(); + if( eof ) + { + ACE_DEBUG((LM_DEBUG, "(%P|%t) Unrecoverable stream error/eof\n" )); + break; + } + else + { + ACE_DEBUG((LM_DEBUG, "(%P|%t) Recoverable stream error (timeout)\n" )); + server.clear(0); + } + } + server >> f1; server >> l; server >> f2; @@ -320,6 +340,10 @@ server (void *arg = 0) // filled or when we flush it with an explicit client.sync() command // or the implicit <<endl. + + ACE_DEBUG ((LM_DEBUG, "(%P|%t) Server sleeping\n" )); + ACE_OS::sleep(30); + ACE_DEBUG ((LM_DEBUG, "(%P|%t) Server Sending: 1 .12342134 666555444 23.45 -46.5e9 \n")); client_handler << 1 << " "; client_handler << .12342134 << " "; |