This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC/Patch] What about using seekoff(-1, ...) for unbufferedunderflow?


Benjamin Kosnik wrote:

If you can prove that using the pback buffer leads to incorrectness, or
a substantial slowdown for buffered sbumpc, than I will be more
favorably inclined in your proposed patch. After all,
__gnu_cxx::stdio_sync_filebuf is what should be used if a speedy
solution (and codecvt lacking interpretation) is desired.

Thanks.

Your aesthetic arguments about _M_buf_size and the purity of
non-virtuals I agree with, but don't find especially compelling. I
remain unconvinced that the performance issues can be measured.

I will help you prove me wrong though!

Here's an idea that may prove the unbuffered pback usage wrong:  you'd
need to do a getc on an unbuffered input stream, then change locales to
one that does the codecvt conversion differently, thus invalidating
(possibly?) the stored pback character. It's hard, but perhaps not
impossible, to prove this, and I'd certainly like to see the test case.
There are some similar proofs done in the testsuite with overflow. (This
is certainly easier than trying to use the pback buffer without
modifying sbumpc....)

You will find attached my second try, along the lines suggested by Nathan
(but honestly I had already started working on it before Nathan's
interesting reply ;)

This means: no seeks (this answers also a concern raised privately by
Pétur as regards pipes), a simple sbumpc().

Seems like a possibility...

However, I agree _completely_ with your concerns (I hadn't considered
locales, damn!) and also, let me add that, even if we don't care much,
this additional use of the single pback char we have available implies
that (both in yours and mine solution) after any sgetc() the pback area
is full! Therefore no chars can be pback at all upon request!
This seems bad.

What to do?

1- Adding another hidden "pback" area only for unbuffered sgetc()-type
situations: this answers my last concern but definitely not yours involving
locales.
2- Resorting to seeks (as in my first proposal): indeed unbuffered sgetc()
would be slowed down but we have a _really_ simple and correct solution.
3- Something else... What????

Paolo.
diff -urN libstdc++-v3-orig/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
--- libstdc++-v3-orig/include/bits/fstream.tcc	2003-06-06 02:19:14.000000000 +0200
+++ libstdc++-v3/include/bits/fstream.tcc	2003-06-06 22:33:47.000000000 +0200
@@ -71,9 +71,9 @@
   template<typename _CharT, typename _Traits>
     basic_filebuf<_CharT, _Traits>::
     basic_filebuf() : __streambuf_type(), _M_file(&_M_lock), 
-    _M_state_cur(__state_type()), _M_state_beg(__state_type()), _M_buf(NULL), 
-    _M_buf_allocated(false),_M_last_overflowed(false), 
-    _M_filepos(0), _M_pback(char_type()), _M_pback_cur_save(0), 
+    _M_state_cur(__state_type()), _M_state_beg(__state_type()),
+    _M_buf(NULL), _M_buf_size(BUFSIZ), _M_buf_allocated(false),
+    _M_last_overflowed(false), _M_filepos(0), _M_pback_cur_save(0),
     _M_pback_end_save(0), _M_pback_init(false), _M_codecvt(0)
     { 
       this->_M_buf_unified = true; 	  
@@ -188,15 +188,15 @@
 
       if (__testin)
 	{
-	  // Check for pback madness, and if so swich back to the
-	  // normal buffers and jet outta here before expensive
-	  // fileops happen...
-	  _M_destroy_pback();
-
 	  const size_t __buflen = this->_M_buf_size 
 	                          ? this->_M_buf_size - 1 : 0;
 	  if (__buflen)
 	    {
+	      // Check for pback madness, and if so swich back to the
+	      // normal buffers and jet outta here before expensive
+	      // fileops happen...
+	      _M_destroy_pback();
+
 	      if (this->_M_in_cur < this->_M_in_end)
 		{
 		  __ret = traits_type::to_int_type(*this->_M_in_cur);
@@ -256,6 +256,14 @@
 	  else
 	    {
 	      // Unbuffered.
+	      if (this->_M_pback_init)
+		{
+		  __ret = traits_type::to_int_type(*this->_M_in_cur);
+		  if (__bump)
+		    _M_destroy_pback();
+		  return __ret;
+		}
+
 	      char __buf;
 	      if (_M_file.xsgetn(&__buf, 1) > 0)
 		{
@@ -285,7 +293,8 @@
 		  if (!__bump)
 		    {
 		      _M_create_pback();
-		      *this->_M_in_cur = traits_type::to_char_type(__ret); 
+		      *this->_M_in_cur = traits_type::to_char_type(__ret);
+		      this->_M_in_end--;
 		    }
 		}
 	    }
diff -urN libstdc++-v3-orig/include/bits/streambuf.tcc libstdc++-v3/include/bits/streambuf.tcc
--- libstdc++-v3-orig/include/bits/streambuf.tcc	2003-06-06 02:19:15.000000000 +0200
+++ libstdc++-v3/include/bits/streambuf.tcc	2003-06-06 18:53:29.000000000 +0200
@@ -48,12 +48,8 @@
       if (_M_in_cur < _M_in_end)
 	{
 	  char_type __c = *this->_M_in_cur;
+	  _M_move_in_cur(1);
 	  __ret = traits_type::to_int_type(__c);
-	  
-	  if (_M_buf_size)
-	    _M_move_in_cur(1);
-	  else
-	    this->underflow();
 	}
       else 
 	__ret = this->uflow();
diff -urN libstdc++-v3-orig/include/std/std_fstream.h libstdc++-v3/include/std/std_fstream.h
--- libstdc++-v3-orig/include/std/std_fstream.h	2003-06-06 02:19:15.000000000 +0200
+++ libstdc++-v3/include/std/std_fstream.h	2003-06-06 22:34:54.000000000 +0200
@@ -121,6 +121,15 @@
       */
       char_type*		_M_buf; 	
 
+      /**
+       *  @if maint
+       *  Actual size of internal buffer. This number is equal to the size
+       *  of the put area + 1 position, reserved for the overflow char of
+       *  a full area.
+       *  @endif
+      */
+      size_t			_M_buf_size;
+
       // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer.
       /**
        *  @if maint
@@ -206,6 +215,7 @@
       ~basic_filebuf()
       {
 	this->close();
+	_M_buf_size = 0;
 	_M_last_overflowed = false;
       }
 
diff -urN libstdc++-v3-orig/include/std/std_streambuf.h libstdc++-v3/include/std/std_streambuf.h
--- libstdc++-v3-orig/include/std/std_streambuf.h	2003-06-06 02:19:15.000000000 +0200
+++ libstdc++-v3/include/std/std_streambuf.h	2003-06-06 22:36:50.000000000 +0200
@@ -197,15 +197,6 @@
 
       /**
        *  @if maint
-       *  Actual size of internal buffer. This number is equal to the size
-       *  of the put area + 1 position, reserved for the overflow char of
-       *  a full area.
-       *  @endif
-      */
-      size_t			_M_buf_size;
-
-      /**
-       *  @if maint
        *  Place to stash in || out || in | out settings for current streambuf.
        *  @endif
       */
@@ -267,7 +258,6 @@
       ~basic_streambuf() 
       {
 	_M_buf_unified = false;
-	_M_buf_size = 0;
 	_M_mode = ios_base::openmode(0);
       }
 
@@ -467,10 +457,9 @@
        *  - this is not an error
       */
       basic_streambuf()
-      : _M_in_beg(0), _M_in_cur(0), _M_in_end(0), 
-      _M_out_beg(0), _M_out_cur(0), _M_out_end(0),_M_out_lim(0), 
-      _M_buf_unified(false), _M_buf_size(BUFSIZ), 
-      _M_mode(ios_base::openmode(0)),_M_buf_locale(locale()) 
+      : _M_in_beg(0), _M_in_cur(0), _M_in_end(0), _M_out_beg(0),
+      _M_out_cur(0), _M_out_end(0), _M_out_lim(0), _M_buf_unified(false),
+      _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()) 
       { }
 
       // [27.5.2.3.1] get area access

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]