This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
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;