IOStream.cpp

Go to the documentation of this file.
00001 // IOStream.cpp,v 4.36 2005/10/28 16:14:52 ossama Exp
00002 
00003 #ifndef ACE_IOSTREAM_CPP
00004 #define ACE_IOSTREAM_CPP
00005 
00006 #include "ace/IOStream.h"
00007 
00008 ACE_RCSID(ace, IOStream, "IOStream.cpp,v 4.36 2005/10/28 16:14:52 ossama Exp")
00009 
00010 #if !defined (ACE_LACKS_ACE_IOSTREAM)
00011 
00012 #  include "ace/OS_NS_errno.h"
00013 #  include "ace/OS_Memory.h"
00014 
00015 ///////////////////////////////////////////////////////////////////////////
00016 
00017 /* Here's a simple example of how iostream's non-virtual operators can
00018    get you in a mess:
00019 
00020   class myiostream : public iostream
00021   {
00022   public:
00023           myiostream& operator>> (String & s)
00024           {
00025                   ...
00026           }
00027   };
00028 
00029   ...
00030 
00031   int i;
00032   String s;
00033   myiostream foo (...);
00034 
00035   foo >> s;
00036   // OK
00037   // invokes myiostream::operator>> (String&) returning myiostream&
00038 
00039   foo >> i;
00040   // OK
00041   // invokes iostream::operator>> (int&) returning iostream&
00042 
00043   foo >> i >> s;
00044   // BAD
00045   // invokes iostream::operator>> (int&) then iostream::operator>> (String&)
00046   //
00047   // What has happened is that the first >> is invoked on the base class and returns
00048   // a reference to iostream.  The second >> has no idea of the ACE_IOStream and
00049   // gets invoked on iostream.  Probably NOT what you wanted!
00050 
00051 
00052   // In order to make all of this work the way you want, you have to do this:
00053 
00054   class myiostream : public iostream
00055   {
00056   public:
00057           myiostream& operator>> (int & i)
00058           {
00059                   return ((myiostream&)iostream::operator>> (i));
00060           }
00061 
00062           myiostream& operator>> (String & s)
00063           {
00064                   ...
00065           }
00066   };
00067 
00068   ...
00069 
00070   int i;
00071   String s;
00072   myiostream foo (...);
00073 
00074   foo >> s;
00075   // OK
00076   // invokes myiostream::operator>> (String&) returning myiostream&
00077 
00078   foo >> i;
00079   // OK
00080   // invokes myiostream::operator>> (int&) returning myiostream&
00081 
00082 
00083   foo >> i >> s;
00084   // OK
00085   // Because you provided operator>> (int&) in class myiostream, that
00086   // function will be invoked by the first >>.  Since it returns
00087   // a myiostream&, the second >> will be invoked as desired.  */
00088 
00089 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00090 
00091 ACE_HANDLE
00092 ACE_Streambuf::get_handle (void)
00093 {
00094   return 0;
00095 }
00096 
00097 ACE_Time_Value *
00098 ACE_Streambuf::recv_timeout (ACE_Time_Value *tv)
00099 {
00100   ACE_Time_Value * rval = recv_timeout_;
00101   if (tv)
00102     {
00103       recv_timeout_value_ = *tv;
00104       recv_timeout_ = &recv_timeout_value_;
00105     }
00106   else
00107     recv_timeout_ = 0;
00108 
00109   return rval;
00110 }
00111 
00112 int
00113 ACE_Streambuf::underflow (void)
00114 {
00115   // If input mode is not set, any attempt to read from the stream is
00116   // a failure.
00117 
00118   if (ACE_BIT_DISABLED (mode_, ios::in))
00119     return EOF;
00120 
00121   // If base () is empty then this is the first time any get/put
00122   // operation has been attempted on the stream.
00123 
00124   if (!this->base ())
00125     {
00126       // Set base () to use our private read buffer.  The arguments are:
00127       //        beginning of the buffer (base ())
00128       //        one-beyond the end of the buffer (ebase ())
00129       //        should base () be deleted on destruction
00130       //
00131       // We have to say "no" to the third parameter because we want to
00132       // explicitly handle deletion of the TWO buffers at destruction.
00133 
00134       setb (this->eback_saved_,
00135             this->eback_saved_ + streambuf_size_, 0);
00136 
00137       // Remember that we are now in getMode.  This will help us if
00138       // we're called prior to a mode change as well as helping us
00139       // when the mode does change.
00140       this->cur_mode_ = this->get_mode_;
00141       // Using the new values for base (), initialize the get area.
00142       // This simply sets eback (), gptr () and egptr () described
00143       // earlier.
00144       setg (base (), base (), base ());
00145 
00146       // Set the put buffer such that puts will be disabled.  Any
00147       // attempt to put data will now cause overflow to be invoked.
00148       setp (0, 0);
00149     }
00150   else  // base () has been initialized already...
00151     {
00152       // If we are in put_mode_ now, then it is time to switch to get_mode_
00153       //
00154       // 1. get rid of any pending output
00155       // 2. rearrange base () to use our half of the buffer
00156       // 3. reset the mode
00157       //
00158       if (this->cur_mode_ == this->put_mode_)
00159         {
00160           // Dump any pending output to the peer.  This is not really
00161           // necessary because of the dual-buffer arrangement we've
00162           // set up but intuitively it makes sense to send the pending
00163           // data before we request data since the peer will probably
00164           // need what we're sending before it can respond.
00165           if (out_waiting () && syncout () == EOF)
00166             return EOF;
00167 
00168           if( ! pbase() )
00169             {
00170               delete [] pbase_saved_;
00171               (void) reset_put_buffer();
00172             }
00173           else
00174             {
00175               // We're about to disable put mode but before we do
00176               // that, we want to preserve it's state.
00177               this->pbase_saved_ = pbase ();
00178               this->pptr_saved_  = pptr ();
00179               this->epptr_saved_ = epptr ();
00180             }
00181 
00182           // Disable put mode as described in the constructor.
00183           setp (0, 0);
00184 
00185           // Like the case where base () is false, we now point base
00186           // () to use our private get buffer.
00187           setb (this->eback_saved_,
00188                 this->eback_saved_ + streambuf_size_,
00189                 0);
00190 
00191           // And restore the previous state of the get pointers.
00192 
00193           setg (this->eback_saved_, this->gptr_saved_,
00194                 this->egptr_saved_);
00195 
00196           // Finally, set our mode so that we don't get back into this
00197           // if () and so that overflow can operate correctly.
00198           cur_mode_ = get_mode_;
00199         }
00200 
00201       // There could be data in the input buffer if we switched to put
00202       // mode before reading everything.  In that case, we take this
00203       // opportunity to feed it back to the iostream.
00204       if (in_avail ())
00205         // Remember that we return an int so that we can give back
00206         // EOF.  The explicit cast prevents us from returning a signed
00207         // char when we're not returning EOF.
00208         return (u_char) *gptr ();
00209     }
00210 
00211   // We really shouldn't be here unless there is a lack of data in the
00212   // read buffer.  So... go get some more data from the peer.
00213 
00214   int result = fillbuf ();
00215 
00216   // Fillbuf will give us EOF if there was an error with the peer.  In
00217   // that case, we can do no more input.
00218 
00219   if (EOF == result)
00220     {
00221       // Disable ourselves and return failure to the iostream.  That
00222       // should result in a call to have oursleves closed.
00223       setg (0, 0, 0);
00224       return EOF;
00225     }
00226 
00227   // Return the next available character in the input buffer.  Again,
00228   // we protect against sign extension.
00229 
00230   return (u_char) *gptr ();
00231 }
00232 
00233 // Much of this is similar to underflow.  I'll just hit the highlights
00234 // rather than repeating a lot of what you've already seen.
00235 
00236 int
00237 ACE_Streambuf::overflow (int c)
00238 {
00239   // Check to see if output is allowed at all.
00240   if (! (mode_ & ios::out))
00241     return EOF;
00242 
00243   if (!base ())
00244     {
00245       // Set base () to use put's private buffer.
00246       //
00247       setb (this->pbase_saved_,
00248             this->pbase_saved_ + streambuf_size_, 0);
00249 
00250       // Set the mode for optimization.
00251       this->cur_mode_ = this->put_mode_;
00252       // Set the put area using the new base () values.
00253       setp (base (), ebuf ());
00254 
00255       // Disable the get area.
00256       setg (0, 0, 0);
00257     }
00258   else  // We're already reading or writing
00259     {
00260       // If we're coming out of get mode...
00261       if (this->cur_mode_ == this->get_mode_)
00262         {
00263           // --> JCEJ 6/6/98
00264           if (! eback())
00265             {
00266               /* Something has happened to cause the streambuf
00267                  to get rid of our get area.
00268                  We could probably do this a bit cleaner but
00269                  this method is sure to cleanup the bits and
00270                  pieces.
00271               */
00272               delete [] eback_saved_;
00273               (void) reset_get_buffer();
00274             }
00275           else
00276             {
00277               // Save the current get mode values
00278               this->eback_saved_ = eback ();
00279               this->gptr_saved_  = gptr ();
00280               this->egptr_saved_ = egptr ();
00281             }
00282           // <-- JCEJ 6/6/98
00283 
00284           // then disable the get buffer
00285           setg (0, 0, 0);
00286 
00287           // Reconfigure base () and restore the put pointers.
00288           setb (pbase_saved_, pbase_saved_ + streambuf_size_, 0);
00289           setp (base (), ebuf ());
00290 
00291           // Save the new mode.
00292           this->cur_mode_ = this->put_mode_;
00293         }
00294 
00295       // If there is output to be flushed, do so now.  We shouldn't
00296       // get here unless this is the case...
00297 
00298       if (out_waiting () && EOF == syncout ())
00299         return EOF;
00300     }
00301 
00302   // If we're not putting EOF, then we have to deal with the character
00303   // that is being put.  Perhaps we should do something special with EOF???
00304 
00305   if (c != EOF)
00306     {
00307       // We've already written any data that may have been in the
00308       // buffer, so we're guaranteed to have room in the buffer for
00309       // this new information.  So... we add it to the buffer and
00310       // adjust our 'next' pointer acordingly.
00311       *pptr () = (char) c;
00312       pbump (1);
00313     }
00314 
00315   return 0;
00316 }
00317 
00318 // syncin
00319 
00320 int
00321 ACE_Streambuf::syncin (void)
00322 {
00323   // As discussed, there really isn't any way to sync input from a
00324   // socket-like device.  We specifially override this base-class
00325   // function so that it won't do anything evil to us.
00326   return 0;
00327 }
00328 
00329 // syncout
00330 
00331 int
00332 ACE_Streambuf::syncout (void)
00333 {
00334   // Unlike syncin, syncout is a doable thing.  All we have to do is
00335   // write whatever is in the output buffer to the peer.  flushbuf ()
00336   // is how we do it.
00337 
00338   if (flushbuf () == EOF)
00339     return EOF;
00340   else
00341     return 0;
00342 }
00343 
00344 int
00345 ACE_Streambuf::sync (void)
00346 {
00347   // sync () is fairly traditional in that it syncs both input and
00348   // output.  We could have omitted the call to syncin () but someday,
00349   // we may want it to do something.
00350 
00351   syncin ();
00352 
00353   // Don't bother syncing the output unless there is data to be
00354   // sent...
00355 
00356   if (out_waiting ())
00357     return syncout ();
00358   else
00359     return 0;
00360 }
00361 
00362 // flushbuf
00363 
00364 int
00365 ACE_Streambuf::flushbuf (void)
00366 {
00367   // pptr () is one character beyond the last character put into the
00368   // buffer.  pbase () points to the beginning of the put buffer.
00369   // Unless pptr () is greater than pbase () there is nothing to be
00370   // sent to the peer.
00371 
00372   if (pptr () <= pbase ())
00373     return 0;
00374 
00375   // 4/12/97 -- JCEJ
00376   // Kludge!!!
00377   // If the remote side shuts down the connection, an attempt to send
00378   // () to the remote will result in the message 'Broken Pipe' I think
00379   // this is an OS message, I've tracked it down to the ACE_OS::write
00380   // () function.  That's the last one to be called before the
00381   // message.  I can only test this on Linux though, so I don't know
00382   // how other systems will react.
00383   //
00384   // To get around this gracefully, I do a PEEK recv () with an
00385   // immediate (nearly) timeout.  recv () is much more graceful on
00386   // it's failure.  If we get -1 from recv () not due to timeout then
00387   // we know we're SOL.
00388   //
00389   // Q:  Is 'errno' threadsafe?  Should the section below be a
00390   //     critical section?
00391   //
00392   // char tbuf[1];
00393   // ACE_Time_Value to (0,1);
00394   // if (this->recv (tbuf, 1, MSG_PEEK, &to) == -1)
00395   // {
00396   //    if (errno != ETIME)
00397   //    {
00398   //            perror ("OOPS preparing to send to peer");
00399   //            return EOF;
00400   //    }
00401   // }
00402   //
00403   // The correct way to handle this is for the application to trap
00404   // (and ignore?) SIGPIPE.  Thanks to Amos Shapira for reminding me
00405   // of this.
00406 
00407   // Starting at the beginning of the buffer, send as much data as
00408   // there is waiting.  send guarantees that all of the data will be
00409   // sent or an error will be returned.
00410 
00411   if (this->send (pbase (), pptr () - pbase ()) == -1)
00412     return EOF;
00413 
00414   // Now that we've sent everything in the output buffer, we reset the
00415   // buffer pointers to appear empty.
00416   setp (base (), ebuf ());
00417 
00418   return 0;
00419 }
00420 
00421 int
00422 ACE_Streambuf::get_one_byte (void)
00423 {
00424   this->timeout_ = 0;
00425 
00426   // The recv function will return immediately if there is no data
00427   // waiting.  So, we use recv_n to wait for exactly one byte to come
00428   // from the peer.  Later, we can use recv to see if there is
00429   // anything else in the buffer. (Ok, we could use flags to tell it
00430   // to block but I like this better.)
00431 
00432   if (this->recv_n (base (), 1, MSG_PEEK, this->recv_timeout_) != 1)
00433     {
00434       if (errno == ETIME)
00435         this->timeout_ = 1;
00436       return EOF;
00437     }
00438   else
00439     return 1;
00440 }
00441 
00442 // This will be called when the read (get) buffer has been exhausted
00443 // (ie -- gptr == egptr).
00444 
00445 int
00446 ACE_Streambuf::fillbuf (void)
00447 {
00448   // Invoke recv_n to get exactly one byte from the remote.  This will
00449   // block until something shows up.
00450 
00451   if (get_one_byte () == EOF)
00452     return EOF;
00453 
00454   // Now, get whatever else may be in the buffer.  This will return if
00455   // there is nothing in the buffer.
00456 
00457   int bc = this->recv (base (), blen (), this->recv_timeout_);
00458 
00459   // recv will give us -1 if there was a problem.  If there was
00460   // nothing waiting to be read, it will give us 0.  That isn't an
00461   // error.
00462 
00463   if (bc < 0)
00464     {
00465       if (errno == ETIME)
00466         this->timeout_ = 1;
00467       return EOF;
00468     }
00469 
00470   // Move the get pointer to reflect the number of bytes we just read.
00471 
00472   setg (base (), base (), base () + bc);
00473 
00474   // Return the byte-read-count including the one from <get_one_byte>.
00475   return bc;
00476 }
00477 
00478 ACE_Streambuf::ACE_Streambuf (u_int streambuf_size, int io_mode)
00479   : eback_saved_ (0),  // to avoid Purify UMR
00480     pbase_saved_ (0),  // to avoid Purify UMR
00481     get_mode_ (1),
00482     put_mode_ (2),
00483     mode_ (io_mode),
00484     streambuf_size_ (streambuf_size),
00485     recv_timeout_ (0)
00486 {
00487  (void)reset_get_buffer ();
00488  (void)reset_put_buffer ();
00489 }
00490 
00491 u_int
00492 ACE_Streambuf::streambuf_size (void)
00493 {
00494   return streambuf_size_;
00495 }
00496 
00497 // Return the number of bytes not yet gotten. eback + get_waiting =
00498 // gptr.
00499 
00500 u_int
00501 ACE_Streambuf::get_waiting (void)
00502 {
00503   return this->gptr_saved_ - this->eback_saved_;
00504 }
00505 
00506 // Return the number of bytes in the get area (includes some already
00507 // gotten); eback + get_avail = egptr.
00508 
00509 u_int
00510 ACE_Streambuf::get_avail (void)
00511 {
00512   return this->egptr_saved_ - this->eback_saved_;
00513 }
00514 
00515 // Return the number of bytes to be 'put' onto the stream media.
00516 // pbase + put_avail = pptr.
00517 
00518 u_int
00519 ACE_Streambuf::put_avail (void)
00520 {
00521   return this->pptr_saved_ - this->pbase_saved_;
00522 }
00523 
00524 // Typical usage:
00525 //
00526 //      u_int  newGptr  = otherStream->get_waiting ();
00527 //      u_int  newEgptr = otherStream->get_avail ();
00528 //      char * newBuf   = otherStream->reset_get_buffer ();
00529 //      char * oldgetbuf = myStream->reset_get_buffer (newBuf, otherStream->streambuf_size (), newGptr, newEgptr);
00530 //
00531 //      'myStream' now has the get buffer of 'otherStream' and can use it in any way.
00532 //      'otherStream' now has a new, empty get buffer.
00533 
00534 char *
00535 ACE_Streambuf::reset_get_buffer (char *newBuffer,
00536                                  u_int _streambuf_size,
00537                                  u_int _gptr,
00538                                  u_int _egptr)
00539 {
00540   char * rval = this->eback_saved_;
00541 
00542   // The get area is where the iostream will get data from.  This is
00543   // our read buffer.  There are three pointers which describe the
00544   // read buffer:
00545   //
00546   //    eback () - The beginning of the buffer.  Also the furthest
00547   //              point at which putbacks can be done.  Hence the name.
00548   //
00549   //    gptr ()  - Where the next character is to be got from.
00550   //
00551   //    egptr () - One position beyond the last get-able character.
00552   //
00553   // So that we can switch quicky from read to write mode without
00554   // any data copying, we keep copies of these three pointers in
00555   // the variables below.  Initially, they all point to the beginning
00556   // of our read-dedicated buffer.
00557   //
00558   if (newBuffer)
00559     {
00560       if (streambuf_size_ != _streambuf_size)
00561         return 0;
00562       this->eback_saved_ = newBuffer;
00563     }
00564   else
00565     ACE_NEW_RETURN (this->eback_saved_,
00566                     char[streambuf_size_],
00567                     0);
00568 
00569   this->gptr_saved_ = this->eback_saved_ + _gptr;
00570   this->egptr_saved_ = this->eback_saved_ + _egptr;
00571 
00572   // Disable the get area initially.  This will cause underflow to be
00573   // invoked on the first get operation.
00574   setg (0, 0, 0);
00575 
00576   reset_base ();
00577 
00578   return rval;
00579 }
00580 
00581 // Typical usage:
00582 //
00583 //      u_int  newPptr = otherStream->put_avail ();
00584 //      char * newBuf  = otherStream->reset_put_buffer ();
00585 //      char * oldputbuf = otherStream->reset_put_buffer (newBuf, otherStream->streambuf_size (), newPptr);
00586 
00587 char *
00588 ACE_Streambuf::reset_put_buffer (char *newBuffer,
00589                                  u_int _streambuf_size,
00590                                  u_int _pptr)
00591 {
00592   char *rval = this->pbase_saved_;
00593 
00594   // The put area is where the iostream will put data that needs to be
00595   // sent to the peer.  This becomes our write buffer.  The three
00596   // pointers which maintain this area are:
00597   //
00598   //    pbase () - The beginning of the put area.
00599   //
00600   //    pptr ()  - Where the next character is to be put.
00601   //
00602   //    epptr () - One beyond the last valid position for putting.
00603   //
00604   // Again to switch quickly between modes, we keep copies of
00605   // these three pointers.
00606   //
00607   if (newBuffer)
00608     {
00609       if (streambuf_size_ != _streambuf_size)
00610         return 0;
00611       this->pbase_saved_ = newBuffer;
00612     }
00613   else
00614     ACE_NEW_RETURN (this->pbase_saved_,
00615                     char[streambuf_size_],
00616                     0);
00617 
00618   this->pptr_saved_ = this->pbase_saved_ + _pptr;
00619   this->epptr_saved_ = this->pbase_saved_ + streambuf_size_;
00620 
00621   // Disable the put area.  Overflow will be called by the first call
00622   // to any put operator.
00623   setp (0, 0);
00624 
00625   reset_base ();
00626 
00627   return rval;
00628 }
00629 
00630 void
00631 ACE_Streambuf::reset_base (void)
00632 {
00633   // Until we experience the first get or put operation, we do not
00634   // know what our current IO mode is.
00635   this->cur_mode_ = 0;
00636 
00637   // The common area used for reading and writting is called "base".
00638   // We initialize it this way so that the first get/put operation
00639   // will have to "allocate" base.  This allocation will set base to
00640   // the appropriate specific buffer and set the mode to the correct
00641   // value.
00642   setb (0, 0);
00643 }
00644 
00645 // If the default allocation strategey were used the common buffer
00646 // would be deleted when the object destructs.  Since we are providing
00647 // separate read/write buffers, it is up to us to manage their memory.
00648 
00649 ACE_Streambuf::~ACE_Streambuf (void)
00650 {
00651   delete [] this->eback_saved_;
00652   delete [] this->pbase_saved_;
00653 }
00654 
00655 u_char ACE_Streambuf::timeout (void)
00656 {
00657   u_char rval = this->timeout_;
00658   this->timeout_ = 0;
00659   return rval;
00660 }
00661 
00662 ACE_END_VERSIONED_NAMESPACE_DECL
00663 
00664 #endif /* !ACE_LACKS_ACE_IOSTREAM */
00665 #endif /* ACE_IOSTREAM_CPP */

Generated on Thu Nov 9 09:41:52 2006 for ACE by doxygen 1.3.6