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]

[Patch] Fix libstdc++/7744


Hi,

this is the fix which we have already discussed at length:
when not synced with stdio, we use read/write/lseek.

Tested x86-linux.

Nathan, I see that going through the code many chances of
more fundamental possibilities of improvement appear to your
eyes (in particular from the performance point of view) on the
other hand our forces are limited, and we still have a good
amount of bugs to fix :(

I hope to return to the former after 9533-9423-9024-9875-9178
and 9964-9988.

Nathan, Benjamin, ok?

Thanks,
Paolo.

P.S. Benjamin, in my private message I forgot _your_ 9780!

//////////
2003-03-09  Paolo Carlini  <pcarlini at unitus dot it>
	    Nathan Myers  <ncm at cantrip dot org>

	PR libstdc++/7744
	* config/io/basic_file_stdio.h (__basic_file<>::xsgetn, xsputn,
	seekoff, seekpos): Add a boolean parameter __stdio.
	* config/io/basic_file_stdio.cc (__basic_file<>::xsgetn, xsputn,
	seekoff, seekpos): If __stdio == true, use fread (fwrite, fseek/ftell,
	fseek/ftell, respectively), otherwise read (write, lseek, lseek,
	respectively).
	* include/bits/fstream.tcc (basic_filebuf<>::_M_convert_to_external,
	_M_really_overflow, seekoff): Use the boolean parameter in the calls.
	* include/std/std_fstream.h (sync): Likewise.
	* src/fstream.cc (basic_filebuf<>::_M_underflow_common): Likewise.
	* src/ios.cc (ios_base::Init::_S_ios_create(bool)): Revert libstdc++/8399
	commit involving isatty(0).
	* acinclude.m4 (GLIBCPP_CHECK_UNISTD_DECL_AND_LINKAGE_1): Remove.
        (GLIBCPP_CHECK_UNISTD_SUPPORT): Remove
  	* configure.in: Remove call.
	* aclocal.m4: Regenerate.
       	* config.h.in: Regenerate.
        * configure: Regenerate.
	* testsuite/27_io/narrow_stream_objects.cc (test11): Add.
diff -urN libstdc++-v3-orig/acinclude.m4 libstdc++-v3/acinclude.m4
--- libstdc++-v3-orig/acinclude.m4	2003-02-11 06:50:01.000000000 +0100
+++ libstdc++-v3/acinclude.m4	2003-03-08 16:34:11.000000000 +0100
@@ -591,34 +591,6 @@
 ])
 
 dnl
-dnl Check to see if the (unistd function) argument passed is
-dnl 1) declared when using the c++ compiler
-dnl 2) has "C" linkage
-dnl
-dnl argument 1 is name of function to check
-dnl
-dnl ASSUMES argument is a function with ONE parameter
-dnl
-dnl GLIBCPP_CHECK_UNISTD_DECL_AND_LINKAGE_1
-AC_DEFUN(GLIBCPP_CHECK_UNISTD_DECL_AND_LINKAGE_1, [
-  AC_MSG_CHECKING([for $1 declaration])
-  if test x${glibcpp_cv_func_$1_use+set} != xset; then
-    AC_CACHE_VAL(glibcpp_cv_func_$1_use, [
-      AC_LANG_SAVE
-      AC_LANG_CPLUSPLUS
-      AC_TRY_COMPILE([#include <unistd.h>],
-                     [ $1(0);],
-                     [glibcpp_cv_func_$1_use=yes], [glibcpp_cv_func_$1_use=no])
-      AC_LANG_RESTORE
-    ])
-  fi
-  AC_MSG_RESULT($glibcpp_cv_func_$1_use)
-  if test x$glibcpp_cv_func_$1_use = x"yes"; then
-    AC_CHECK_FUNCS($1)
-  fi
-])
-
-dnl
 dnl Because the builtins are picky picky picky about the arguments they take,
 dnl do an explict linkage tests here.
 dnl Check to see if the (math function) argument passed is
@@ -753,26 +725,6 @@
 ])
 
 dnl
-dnl Check to see what the underlying c library is like
-dnl These checks need to do two things:
-dnl 1) make sure the name is declared when using the c++ compiler
-dnl 2) make sure the name has "C" linkage
-dnl This might seem like overkill but experience has shown that it's not...
-dnl
-dnl Define HAVE_ISATTY if "isatty" is declared and links
-dnl
-dnl GLIBCPP_CHECK_UNISTD_SUPPORT
-AC_DEFUN(GLIBCPP_CHECK_UNISTD_SUPPORT, [
-  ac_test_CXXFLAGS="${CXXFLAGS+set}"
-  ac_save_CXXFLAGS="$CXXFLAGS"
-  CXXFLAGS='-fno-builtins -D_GNU_SOURCE'
-
-  GLIBCPP_CHECK_UNISTD_DECL_AND_LINKAGE_1(isatty)
-
-  CXXFLAGS="$ac_save_CXXFLAGS"
-])
-
-dnl
 dnl Check to see what the underlying c library or math library is like.
 dnl These checks need to do two things:
 dnl 1) make sure the name is declared when using the c++ compiler
diff -urN libstdc++-v3-orig/config/io/basic_file_stdio.cc libstdc++-v3/config/io/basic_file_stdio.cc
--- libstdc++-v3-orig/config/io/basic_file_stdio.cc	2003-02-04 23:42:32.000000000 +0100
+++ libstdc++-v3/config/io/basic_file_stdio.cc	2003-03-09 09:27:26.000000000 +0100
@@ -1,6 +1,6 @@
 // Wrapper of C-language FILE struct -*- C++ -*-
 
-// Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -33,6 +33,7 @@
 
 #include <bits/basic_file.h>
 #include <fcntl.h>
+#include <errno.h>
 
 namespace std 
 {
@@ -191,33 +192,69 @@
     return __retval;
   }
  
+  // In the next four functions we want to use stdio functions only
+  // when synced with stdio (_M_buf_size == 1): I/O primitives do not
+  // block until the asked number of bytes is available.
   streamsize 
-  __basic_file<char>::xsgetn(char* __s, streamsize __n)
-  { return fread(__s, 1, __n, _M_cfile); }
-  
+  __basic_file<char>::xsgetn(char* __s, streamsize __n, bool __stdio)
+  {
+    if (__stdio)
+      return fread(__s, 1, __n, _M_cfile);
+    else
+      {
+	streamsize __ret;
+        do
+	  __ret = read(this->fd(), __s, __n);
+	while (__ret == -1L && errno == EINTR);
+	return __ret;
+      }
+  }
+    
   streamsize 
-  __basic_file<char>::xsputn(const char* __s, streamsize __n)
-  { return fwrite(__s, 1, __n, _M_cfile); }
+  __basic_file<char>::xsputn(const char* __s, streamsize __n, bool __stdio)
+  {
+    if (__stdio)
+      return fwrite(__s, 1, __n, _M_cfile);
+    else
+      {
+	streamsize __ret;
+        do
+	  __ret = write(this->fd(), __s, __n);
+	while (__ret == -1L && errno == EINTR);
+	return __ret;
+      }
+  }
   
   streamoff
   __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way, 
-			      ios_base::openmode /*__mode*/)
+			      bool __stdio, ios_base::openmode /*__mode*/)
   { 
-    if (!fseek(_M_cfile, __off, __way))
-      return ftell(_M_cfile); 
+    if (!__stdio)
+      return lseek(this->fd(), __off, __way);
     else
-      // Fseek failed.
-      return -1L;
+      {
+	if (!fseek(_M_cfile, __off, __way))
+	  return ftell(_M_cfile); 
+	else
+	  // Fseek failed.
+	  return -1L;
+      }
   }
 
   streamoff
-  __basic_file<char>::seekpos(streamoff __pos, ios_base::openmode /*__mode*/)
+  __basic_file<char>::seekpos(streamoff __pos, bool __stdio,
+			      ios_base::openmode /*__mode*/)
   { 
-    if (!fseek(_M_cfile, __pos, ios_base::beg))
-      return ftell(_M_cfile);
+    if (!__stdio)
+      return lseek(this->fd(), __pos, ios_base::beg);
     else
-      // Fseek failed.
-      return -1L;
+      {
+	if (!fseek(_M_cfile, __pos, ios_base::beg))
+	  return ftell(_M_cfile);
+	else
+	  // Fseek failed.
+	  return -1L;
+      }
   }
   
   int 
diff -urN libstdc++-v3-orig/config/io/basic_file_stdio.h libstdc++-v3/config/io/basic_file_stdio.h
--- libstdc++-v3-orig/config/io/basic_file_stdio.h	2002-04-30 21:04:35.000000000 +0200
+++ libstdc++-v3/config/io/basic_file_stdio.h	2003-03-08 23:11:26.000000000 +0100
@@ -93,17 +93,17 @@
       ~__basic_file();
 
       streamsize 
-      xsputn(const char* __s, streamsize __n);
+      xsputn(const char* __s, streamsize __n, bool __stdio);
 
       streamsize 
-      xsgetn(char* __s, streamsize __n);
+      xsgetn(char* __s, streamsize __n, bool __stdio);
 
       streamoff
-      seekoff(streamoff __off, ios_base::seekdir __way,
+      seekoff(streamoff __off, ios_base::seekdir __way, bool __stdio,
 	      ios_base::openmode __mode = ios_base::in | ios_base::out);
 
       streamoff
-      seekpos(streamoff __pos, 
+      seekpos(streamoff __pos, bool __stdio,
 	      ios_base::openmode __mode = ios_base::in | ios_base::out);
 
       int 
diff -urN libstdc++-v3-orig/configure.in libstdc++-v3/configure.in
--- libstdc++-v3-orig/configure.in	2003-02-20 10:08:30.000000000 +0100
+++ libstdc++-v3/configure.in	2003-03-08 16:35:08.000000000 +0100
@@ -411,7 +411,6 @@
   GLIBCPP_CHECK_COMPLEX_MATH_SUPPORT
   GLIBCPP_CHECK_WCHAR_T_SUPPORT
   GLIBCPP_CHECK_STDLIB_SUPPORT
-  GLIBCPP_CHECK_UNISTD_SUPPORT
   AC_LC_MESSAGES
 
   AC_TRY_COMPILE([
diff -urN libstdc++-v3-orig/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
--- libstdc++-v3-orig/include/bits/fstream.tcc	2003-03-07 23:17:22.000000000 +0100
+++ libstdc++-v3/include/bits/fstream.tcc	2003-03-09 09:25:41.000000000 +0100
@@ -102,7 +102,7 @@
 	      // using underflow.
  	      if (__mode & ios_base::in && _M_buf_allocated)
  		this->underflow();
-	      
+
 	      if ((__mode & ios_base::ate)
 		  && this->seekoff(0, ios_base::end, __mode) < 0)
 		{
@@ -274,10 +274,13 @@
     {
       const locale __loc = this->getloc();
       const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
-      
+      // Sync with stdio.
+      bool __sync = this->_M_buf_size == 1;
+
       if (__cvt.always_noconv() && __ilen)
 	{
-	  __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
+	  __elen +=
+	    _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen, __sync);
 	  __plen += __ilen;
 	}
       else
@@ -307,7 +310,7 @@
 	  
 	  if (__blen)
 	    {
-	      __elen += _M_file.xsputn(__buf, __blen);
+	      __elen += _M_file.xsputn(__buf, __blen, __sync);
 	      __plen += __blen;
 	    }
 
@@ -329,7 +332,7 @@
 		}
 	      if (__rlen)
 		{
-		  __elen += _M_file.xsputn(__buf, __rlen);
+		  __elen += _M_file.xsputn(__buf, __rlen, __sync);
 		  __plen += __rlen;
 		}
 	    }
@@ -344,6 +347,8 @@
       int_type __ret = traits_type::eof();
       bool __testput = this->_M_out_cur && this->_M_out_beg < this->_M_out_lim;
       bool __testunbuffered = _M_file.is_open() && !this->_M_buf_size_opt;
+      // Sync with stdio.
+      bool __sync = this->_M_buf_size == 1;
 
       if (__testput || __testunbuffered)
 	{
@@ -357,7 +362,7 @@
 	  if (_M_filepos && _M_filepos != this->_M_out_beg)
 	    {
 	      off_type __off = this->_M_out_beg - _M_filepos;
-	      _M_file.seekoff(__off, ios_base::cur);
+	      _M_file.seekoff(__off, ios_base::cur, __sync);
 	    }
 
 	  // Convert internal buffer to external representation, output.
@@ -432,7 +437,9 @@
       pos_type __ret =  pos_type(off_type(-1)); 
       bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
       bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
-
+      // Sync with stdio.
+      bool __sync = this->_M_buf_size == 1;
+      
       // Should probably do has_facet checks here.
       int __width = use_facet<__codecvt_type>(this->_M_buf_locale).encoding();
       if (__width < 0)
@@ -466,7 +473,7 @@
 		__computed_off += this->_M_in_cur - _M_filepos;
 
 	      // Return pos_type(off_type(-1)) in case of failure.
-	      __ret = _M_file.seekoff(__computed_off, __way, __mode);
+	      __ret = _M_file.seekoff(__computed_off, __way, __sync, __mode);
 	      _M_set_indeterminate();
 	    }
 	  // NB: Need to do this in case _M_file in indeterminate
@@ -474,7 +481,7 @@
 	  else
 	    {
 	      pos_type __tmp =
-		_M_file.seekoff(__off, ios_base::cur, __mode);
+		_M_file.seekoff(__off, ios_base::cur, __sync, __mode);
 	      if (__tmp >= 0)
 		{
 		  // Seek successful.
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-03-07 22:30:22.000000000 +0100
+++ libstdc++-v3/include/std/std_fstream.h	2003-03-08 23:08:33.000000000 +0100
@@ -314,6 +314,7 @@
 	int __ret = 0;
 	bool __testput = this->_M_out_cur
 	  && this->_M_out_beg < this->_M_out_lim;
+	bool __synced = this->_M_buf_size == 1;
 
 	// Make sure that the internal buffer resyncs its idea of
 	// the file position with the external file.
@@ -327,7 +328,7 @@
 					 traits_type::eof()))
 	      __ret = -1;
 	    else if (__off)
-	      _M_file.seekoff(__off, ios_base::cur);
+	      _M_file.seekoff(__off, ios_base::cur, __synced);
 	  }
 	else
 	  _M_file.sync();
diff -urN libstdc++-v3-orig/src/fstream.cc libstdc++-v3/src/fstream.cc
--- libstdc++-v3-orig/src/fstream.cc	2003-02-24 21:39:31.000000000 +0100
+++ libstdc++-v3/src/fstream.cc	2003-03-09 00:15:30.000000000 +0100
@@ -43,6 +43,8 @@
       int_type __ret = traits_type::eof();
       bool __testin = _M_mode & ios_base::in;
       bool __testout = _M_mode & ios_base::out;
+      // Sync with stdio.
+      bool __sync = _M_buf_size == 1;
 
       if (__testin)
 	{
@@ -71,15 +73,16 @@
 		_M_really_overflow();
 	      else if (_M_in_cur != _M_filepos)
 		_M_file.seekoff(_M_in_cur - _M_filepos,
-				ios_base::cur, ios_base::in);
+				ios_base::cur, __sync, ios_base::in);
 	    }
 
 	  if (__testinit || __testget)
 	    {
 	      streamsize __elen = 0;
 	      streamsize __ilen = 0;
+
 	      __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg), 
-				      _M_buf_size);
+				      _M_buf_size, __sync);
 	      __ilen = __elen;
 
 	      if (0 < __ilen)
@@ -90,7 +93,7 @@
 		  __ret = traits_type::to_int_type(*_M_in_cur);
 		  if (__bump)
 		    _M_in_cur_move(1);
-		  else if (_M_buf_size == 1)
+		  else if (__sync)
 		    {
 		      // If we are synced with stdio, we have to unget the
 		      // character we just read so that the file pointer
@@ -123,6 +126,8 @@
       int_type __ret = traits_type::eof();
       bool __testin = _M_mode & ios_base::in;
       bool __testout = _M_mode & ios_base::out;
+      // Sync with stdio.
+      bool __sync = _M_buf_size == 1;
 
       if (__testin)
 	{
@@ -151,7 +156,7 @@
 		_M_really_overflow();
 	      else if (_M_in_cur != _M_filepos)
 		_M_file.seekoff(_M_in_cur - _M_filepos,
-				ios_base::cur, ios_base::in);
+				  ios_base::cur, __sync, ios_base::in);
 	    }
 
 	  if (__testinit || __testget)
@@ -164,13 +169,13 @@
 	      if (__cvt.always_noconv())
 		{
 		  __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg), 
-					  _M_buf_size);
+					  _M_buf_size, __sync);
 		  __ilen = __elen;
 		}
 	      else
 		{
 		  char* __buf = static_cast<char*>(__builtin_alloca(_M_buf_size));
-		  __elen = _M_file.xsgetn(__buf, _M_buf_size);
+		  __elen = _M_file.xsgetn(__buf, _M_buf_size, __sync);
 
 		  const char* __eend;
 		  char_type* __iend;
@@ -183,7 +188,7 @@
 		    {
 		      // Unwind.
 		      __ilen = 0;
-		      _M_file.seekoff(-__elen, ios_base::cur, ios_base::in);
+		      _M_file.seekoff(-__elen, ios_base::cur, __sync, ios_base::in);
 		    }
 		}
 
@@ -195,7 +200,7 @@
 		  __ret = traits_type::to_int_type(*_M_in_cur);
 		  if (__bump)
 		    _M_in_cur_move(1);
-		  else if (_M_buf_size == 1)
+		  else if (__sync)
 		    {
 		      // If we are synced with stdio, we have to unget the
 		      // character we just read so that the file pointer
diff -urN libstdc++-v3-orig/src/ios.cc libstdc++-v3/src/ios.cc
--- libstdc++-v3-orig/src/ios.cc	2003-03-08 09:13:02.000000000 +0100
+++ libstdc++-v3/src/ios.cc	2003-03-08 16:29:02.000000000 +0100
@@ -38,9 +38,6 @@
 #include <fstream>
 #include <bits/atomicity.h>
 #include <ext/stdio_filebuf.h>
-#ifdef _GLIBCPP_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 
 namespace __gnu_cxx
 {
@@ -160,12 +157,7 @@
   ios_base::Init::_S_ios_create(bool __sync)
   {
     size_t __out_size = __sync ? 0 : static_cast<size_t>(BUFSIZ);
-#ifdef _GLIBCPP_HAVE_ISATTY
-    size_t __in_size =
-      (__sync || isatty (0)) ? 1 : static_cast<size_t>(BUFSIZ);
-#else
-    size_t __in_size = 1;
-#endif
+    size_t __in_size = __sync ? 1 : static_cast<size_t>(BUFSIZ);
 
     // NB: The file globals.cc creates the four standard files
     // with NULL buffers. At this point, we swap out the dummy NULL
diff -urN libstdc++-v3-orig/testsuite/27_io/narrow_stream_objects.cc libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc
--- libstdc++-v3-orig/testsuite/27_io/narrow_stream_objects.cc	2002-08-09 08:00:46.000000000 +0200
+++ libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc	2003-03-08 16:54:46.000000000 +0100
@@ -204,6 +204,22 @@
   cout << "_M_gcount: "<< cin.gcount() << endl;
 }
 
+// libstdc++/7744
+void test11()
+{
+  std::ios::sync_with_stdio(false);
+
+  std::cout
+    << "\n:: f2() ::\n"
+    << "Type in the characters 'abc' and press <ENTER>: ";
+  std::cin.peek();
+ 
+  std::cout
+    << "The number of unread characters should be 4 (a, b, c, \\n): "
+    << std::cin.rdbuf()->in_avail()
+    << '\n';
+}
+
 int 
 main()
 {
@@ -218,5 +234,6 @@
   // test08();
   // test09();
   // test10();
+  // test11();
   return 0;
 }
 

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