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: More on PR libstdc++/10276 (was Re: zero-alloc cache)


Carlo Wood writes:
 > On Wed, Apr 30, 2003 at 12:58:00AM -0400, Jerry Quinn wrote:
 > > I just want to point out that the leak in the original PR is now
 > > plugged.  What is still left is trying to make no calls to new.  So
 > > perhaps 3.3 release doesn't have to be gated by this issue.
 > 
 > I think I can come up with a workaround for libcwd
 > provided that any allocations done are NOT allocated with
 > the standard allocator (thus: not using std::string!).
 > Otherwise there is no way for me to get things working
 > in the threaded case.
 > 
 > When only calls to 'new' and/or 'malloc' are made then
 > its possible to get things working - when these allocations
 > are also deleted again before the function returns (temporary
 > allocations thus) then there is hardly any problem.
 > 
 > I'd really like this to be fixed - therefore, can you send
 > me the diff relative to the current CVS that you have so far,
 > OR apply the patch to CVS, and then tell me the source file
 > locations where std::string is being used that need to be
 > eliminated?  Then I'll have a shot at it.

Here's what I have at the moment.  It includes the changes in
http://gcc.gnu.org/ml/libstdc++/2003-04/msg00443.html.
On top of that, I cobbled up a simple string-like wrapper for char
bufs that includes non-allocated storage for up to 8 chars -
sufficient for POSIX true, false, and grouping.

This is (obviously :-) NOT in finished form.

Jerry


Index: config/linker-map.gnu
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/config/linker-map.gnu,v
retrieving revision 1.25.2.7
diff -u -r1.25.2.7 linker-map.gnu
--- config/linker-map.gnu	7 Mar 2003 22:04:18 -0000	1.25.2.7
+++ config/linker-map.gnu	30 Apr 2003 13:16:31 -0000
@@ -374,6 +374,9 @@
 
   _ZNKSt7num_putI[wc]St19ostreambuf_iteratorI[wc]St11char_traitsI[wc]EEE12_M_group_int*;
 
+    _ZNSt9basic_iosI[cw]St11char_traitsI[cw]EE4initEPSt15basic_streambufI[cw]S1_EPSt14__locale_cacheI[cw]E;
+
+
     # vtable
     _ZTVSt19__locale_cache_base;
     _ZTVSt14__locale_cacheI[cw]E;
Index: include/bits/basic_ios.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/basic_ios.h,v
retrieving revision 1.14.2.4
diff -u -r1.14.2.4 basic_ios.h
--- include/bits/basic_ios.h	22 Apr 2003 15:40:34 -0000	1.14.2.4
+++ include/bits/basic_ios.h	30 Apr 2003 13:16:31 -0000
@@ -425,8 +425,11 @@
        *  memory.
       */
       void 
+      init(basic_streambuf<_CharT, _Traits>* __sb);
+
+      void 
       init(basic_streambuf<_CharT, _Traits>* __sb,
- 	   __locale_cache<_CharT>* __cache=0);
+ 	   __locale_cache<_CharT>* __cache);
 
       bool
       _M_check_facet(const locale::facet* __f) const
Index: include/bits/basic_ios.tcc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/basic_ios.tcc,v
retrieving revision 1.17.4.3
diff -u -r1.17.4.3 basic_ios.tcc
--- include/bits/basic_ios.tcc	22 Apr 2003 15:40:34 -0000	1.17.4.3
+++ include/bits/basic_ios.tcc	30 Apr 2003 13:16:31 -0000
@@ -144,6 +144,11 @@
 
   template<typename _CharT, typename _Traits>
     void
+    basic_ios<_CharT, _Traits>::init(basic_streambuf<_CharT, _Traits>* __sb)
+    { init(__sb, 0); }
+
+  template<typename _CharT, typename _Traits>
+    void
     basic_ios<_CharT, _Traits>::init(basic_streambuf<_CharT, _Traits>* __sb,
 				     __locale_cache<_CharT>* __cache)
     {
@@ -196,7 +201,7 @@
 	// be deleted.
 	if (__cache)
 	  {
-	    pword(0) = auto_ptr<__cache_t>(new (__cache) __cache_t()).release();
+	    pword(0) = auto_ptr<__cache_t>(new (__cache) __cache_t(true)).release();
 	    iword(0) = 1;		// so we don't try to clobber static cache
 	  }
 	else
Index: include/bits/ios_base.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/ios_base.h,v
retrieving revision 1.21.2.5
diff -u -r1.21.2.5 ios_base.h
--- include/bits/ios_base.h	5 Mar 2003 19:09:45 -0000	1.21.2.5
+++ include/bits/ios_base.h	30 Apr 2003 13:16:32 -0000
@@ -376,6 +376,8 @@
     iostate 	       	_M_streambuf_state;
     //@}
 
+    friend class __locale_cache_base;
+
     // 27.4.2.6  Members for callbacks
     // 27.4.2.6  ios_base callbacks
     struct _Callback_list
Index: include/bits/locale_facets.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/locale_facets.h,v
retrieving revision 1.49.4.6
diff -u -r1.49.4.6 locale_facets.h
--- include/bits/locale_facets.h	5 Mar 2003 04:40:07 -0000	1.49.4.6
+++ include/bits/locale_facets.h	30 Apr 2003 13:16:32 -0000
@@ -845,6 +845,9 @@
       do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, bool&) const;
 #endif
 
+  template <typename _CharT>
+  class __string;
+
   template<typename _CharT, typename _OutIter>
     class num_put : public locale::facet, public __num_base
     {
@@ -902,7 +905,8 @@
 			 char __mod, _ValueT __v) const;
 
       void
-      _M_group_float(const string& __grouping, char_type __sep, 
+//       _M_group_float(const string& __grouping, char_type __sep, 
+      _M_group_float(const __string<char>& __grouping, char_type __sep, 
 		     const char_type* __p, char_type* __new, char_type* __cs,
 		     int& __len) const;
 
@@ -912,7 +916,8 @@
 		       _ValueT __v) const;
 
       void
-      _M_group_int(const string& __grouping, char_type __sep, 
+//       _M_group_int(const string& __grouping, char_type __sep, 
+      _M_group_int(const __string<char>& __grouping, char_type __sep, 
 		   ios_base& __io, char_type* __new, char_type* __cs, 
 		   int& __len) const;
 
@@ -1964,11 +1969,66 @@
   // calling the virtual functions in locale facets.
   class __locale_cache_base
   {
+    friend class ios_base;
+
+    // Used to provide space for a callback list entry for static caches.
+    char _M_static_cblist[sizeof(ios_base::_Callback_list)];
+
   public:
     virtual
     ~__locale_cache_base() {}
   };
 
+      // Simple string wrapper.  Assumes strings are null-terminated
+      // as necessary.
+      template <typename _CharT>
+      class __string
+      {
+	_CharT _M_buf[8];
+	_CharT* _M_bufptr;
+	int _M_buflen;
+	int _M_len;
+      public:
+	__string() : _M_bufptr(_M_buf), _M_buflen(8), _M_len(0) { _M_buf[0] = 0; }
+	__string(const _CharT* __s, int __len)
+	  : _M_bufptr(_M_buf), _M_buflen(8), _M_len(__len)
+	{ assign(__s, __len); }
+	__string(const __string& __s)
+	  : _M_bufptr(_M_buf), _M_buflen(8), _M_len(__len)
+	{ assign(__s._M_bufptr, __s._M_len); }
+	~__string() { if (_M_bufptr != _M_buf) delete[] _M_bufptr; }
+
+	__string& operator=(const __string& __s)
+	{
+	  assign(__s._M_bufptr, __s._M_len);
+	  return *this;
+	}
+	__string& operator=(const basic_string<_CharT>& __s)
+	{
+	  assign(__s.c_str(), __s.length()+1);
+	  return *this;
+	}
+
+	void assign(const _CharT* __s, int __len)
+	  {
+	    if (__len >= _M_buflen) {
+	      if (_M_bufptr != _M_buf)
+		delete[] _M_bufptr;
+	      _M_bufptr = new _CharT[__len+1];
+	      _M_buflen = __len+1;
+	    }
+	    memcpy(_M_bufptr, __s, sizeof(_CharT)*(__len+1));
+	    _M_len = __len;
+	  }
+
+	int length() const { return _M_len; }
+	int size() const { return _M_len; }
+
+	const _CharT* c_str() const { return _M_bufptr; }
+	_CharT operator[](int __index) const { return _M_bufptr[__index]; }
+	
+      };
+
   template<typename _CharT>
     class __locale_cache : public __locale_cache_base
     {
@@ -1977,6 +2037,14 @@
       typedef char_traits<_CharT>       traits_type;
       typedef basic_string<_CharT>	string_type;
 
+      // Used to play ugly games for static standard streams
+      int _M_is_static;
+
+      _CharT _M_true_buf[8];
+      _CharT _M_false_buf[8];
+      _CharT _M_group_buf[8];
+
+    public:
 
     public: 
       // Data Members:
@@ -2001,8 +2069,10 @@
       
       // However the US's "false" and "true" are translated.
       // From numpunct::truename() and numpunct::falsename(), respectively.
-      string_type 		_M_truename;
-      string_type 		_M_falsename;
+//       string_type 		_M_truename;
+//       string_type 		_M_falsename;
+      __string<_CharT> _M_truename;
+      __string<_CharT> _M_falsename;
 
       // If we are checking groupings. This should be equivalent to 
       // numpunct::groupings().size() != 0
@@ -2010,10 +2080,18 @@
 
       // If we are using numpunct's groupings, this is the current grouping
       // string in effect (from numpunct::grouping()).
-      string                    _M_grouping;
+      //      string                    _M_grouping;
+      __string<char> _M_grouping;
 
-      __locale_cache() : _M_use_grouping(false)
+      __locale_cache(bool __is_static=false) :
+// 	_M_is_static(__is_static), _M_truename(_M_true_buf), _M_falsename(_M_false_buf),
+// 			 _M_use_grouping(false), _M_grouping(_M_group_buf)
+ 	_M_is_static(__is_static),_M_use_grouping(false)
       { };
+
+//       ~__locale_cache()
+//         {
+// 	}
 
       __locale_cache&
       operator=(const __locale_cache& __lc);
Index: include/bits/locale_facets.tcc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.82.4.9
diff -u -r1.82.4.9 locale_facets.tcc
--- include/bits/locale_facets.tcc	22 Apr 2003 15:40:34 -0000	1.82.4.9
+++ include/bits/locale_facets.tcc	30 Apr 2003 13:16:33 -0000
@@ -730,7 +730,7 @@
   template<typename _CharT, typename _OutIter>
     void
     num_put<_CharT, _OutIter>::
-    _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, 
+    _M_group_int(const __string<char>& __grouping, _CharT __sep, ios_base& __io, 
 		 _CharT* __new, _CharT* __cs, int& __len) const
     {
       // By itself __add_grouping cannot deal correctly with __ws when
@@ -816,7 +816,7 @@
   template<typename _CharT, typename _OutIter>
     void
     num_put<_CharT, _OutIter>::
-    _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, 
+    _M_group_float(const __string<char>& __grouping, _CharT __sep, const _CharT* __p, 
 		   _CharT* __new, _CharT* __cs, int& __len) const
     {
 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
@@ -977,15 +977,20 @@
         {
 	  typedef __locale_cache<_CharT> __cache_type;
 	  __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
-	  typedef basic_string<_CharT> 	__string_type;
-	  __string_type __name;
-          if (__v)
-	    __name = __lc._M_truename;
-          else
-	    __name = __lc._M_falsename;
+// 	  typedef basic_string<_CharT> 	__string_type;
+// 	  __string_type __name;
+//           if (__v)
+// 	    __name = __lc._M_truename;
+//           else
+// 	    __name = __lc._M_falsename;
 
+// 	  const _CharT* __cs = __name.c_str();
+// 	  int __len = __name.size();
+
+	  __string<_CharT>& __name = __v ? __lc._M_truename : __lc._M_falsename;
 	  const _CharT* __cs = __name.c_str();
 	  int __len = __name.size();
+
 	  _CharT* __cs3;
 	  streamsize __w = __io.width();
 	  if (__w > static_cast<streamsize>(__len))
@@ -2275,7 +2280,8 @@
           _M_decimal_point = __np.decimal_point();
           _M_grouping = __np.grouping();
           _M_use_grouping = _M_grouping.size() != 0 
-                            && _M_grouping.data()[0] != 0;
+                            && _M_grouping[0] != 0;
+//                             && _M_grouping.data()[0] != 0;
         }
       if (__builtin_expect(has_facet<ctype<_CharT> >(__loc), true))
         {
Index: include/std/std_istream.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/std/std_istream.h,v
retrieving revision 1.5.2.2
diff -u -r1.5.2.2 std_istream.h
--- include/std/std_istream.h	23 Apr 2003 16:44:15 -0000	1.5.2.2
+++ include/std/std_istream.h	30 Apr 2003 13:16:33 -0000
@@ -107,6 +107,12 @@
 	_M_gcount = streamsize(0);
       }
 
+      basic_istream(__streambuf_type* __sb, __locale_cache<_CharT>* __lc)
+      { 
+	this->init(__sb, __lc);
+	_M_gcount = streamsize(0);
+      }
+
       /**
        *  @brief  Base destructor.
        *
Index: include/std/std_ostream.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/std/std_ostream.h,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 std_ostream.h
--- include/std/std_ostream.h	9 Mar 2003 02:00:53 -0000	1.5.2.1
+++ include/std/std_ostream.h	30 Apr 2003 13:16:33 -0000
@@ -105,6 +105,9 @@
       basic_ostream(__streambuf_type* __sb)
       { this->init(__sb); }
 
+      basic_ostream(__streambuf_type* __sb, __locale_cache<_CharT>* __lc)
+      { this->init(__sb, __lc); }
+
       /**
        *  @brief  Base destructor.
        *
Index: src/ios.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/ios.cc,v
retrieving revision 1.33.2.6
diff -u -r1.33.2.6 ios.cc
--- src/ios.cc	22 Apr 2003 15:40:34 -0000	1.33.2.6
+++ src/ios.cc	30 Apr 2003 13:16:34 -0000
@@ -182,14 +182,10 @@
     new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in, __in_size);
     new (&buf_cerr) stdio_filebuf<char>(stderr, ios_base::out, __out_size);
 
-    new (&cout) ostream(&buf_cout);
-    new (&cin) istream(&buf_cin);
-    new (&cerr) ostream(&buf_cerr);
-    new (&clog) ostream(&buf_cerr);
-    cout.init(&buf_cout, &locale_cache_cout);
-    cin.init(&buf_cin, &locale_cache_cin);
-    cerr.init(&buf_cerr, &locale_cache_cerr);
-    clog.init(&buf_cerr, &locale_cache_clog);
+    new (&cout) ostream(&buf_cout, &locale_cache_cout);
+    new (&cin) istream(&buf_cin, &locale_cache_cin);
+    new (&cerr) ostream(&buf_cerr, &locale_cache_cerr);
+    new (&clog) ostream(&buf_cerr, &locale_cache_clog);
     cin.tie(&cout);
     cerr.flags(ios_base::unitbuf);
     
@@ -197,14 +193,10 @@
     new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size);
     new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in, __in_size);
     new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size);
-    new (&wcout) wostream(&buf_wcout);
-    new (&wcin) wistream(&buf_wcin);
-    new (&wcerr) wostream(&buf_wcerr);
-    new (&wclog) wostream(&buf_wcerr);
-    wcout.init(&buf_wcout, &locale_cache_wcout);
-    wcin.init(&buf_wcin, &locale_cache_wcin);
-    wcerr.init(&buf_wcerr, &locale_cache_wcerr);
-    wclog.init(&buf_wcerr, &locale_cache_wclog);
+    new (&wcout) wostream(&buf_wcout, &locale_cache_wcout);
+    new (&wcin) wistream(&buf_wcin, &locale_cache_wcin);
+    new (&wcerr) wostream(&buf_wcerr, &locale_cache_wcerr);
+    new (&wclog) wostream(&buf_wcerr, &locale_cache_wclog);
     wcin.tie(&wcout);
     wcerr.flags(ios_base::unitbuf);
 #endif
@@ -339,7 +331,18 @@
 
   void 
   ios_base::register_callback(event_callback __fn, int __index)
-  { _M_callbacks = new _Callback_list(__fn, __index, _M_callbacks); }
+  {
+    // Deal with static standard streams.  For these, we didn't want
+    // Callback_list objects to be created on the heap.  Instead we
+    // use the buffer in the cache.
+    if (__index == 0 && iword(0) == 1)
+      {
+	char* __cb_array = _M_cache()._M_static_cblist;
+	_M_callbacks = new (__cb_array) _Callback_list(__fn, __index, _M_callbacks);
+      }
+    else
+      _M_callbacks = new _Callback_list(__fn, __index, _M_callbacks);
+  }
 
   void 
   ios_base::_M_call_callbacks(event __e) throw()
@@ -362,7 +365,9 @@
     while (__p && __p->_M_remove_reference() == 0)
       {
 	_Callback_list* __next = __p->_M_next;
-	delete __p;
+	// Don't delete _Callback_list that is part of a static cache.
+	if (!(__p->_M_index == 0 && iword(0) == 1))
+	  delete __p;
 	__p = __next;
       }
     _M_callbacks = 0;


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