Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

IOStream.cpp

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

Generated on Mon Jun 16 11:19:54 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002