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 */
1.2.14 written by Dimitri van Heesch,
© 1997-2002