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]

Re: Writing to ostreams from operator new.


On Wed, Oct 10, 2001 at 08:52:29PM -0500, Loren James Rittle wrote:
> Hi Carlo,
> 
> If you write a patch that improves the quality of the implementation
> without hurting anything else, then I would tend to believe that your
> patch would be acceptable.
> 
> I think it is too late for 3.0.3 unless it is a trivial patch.
> 
> Regarding exactly what you intend to do, I have no comment until I see
> a patch.  I admit that I am a little bit skeptical of any approach
> that bypasses a critical region lock.  It would seem to be better to
> just force the use of a different allocator (i.e. the one that maps
> directly to plain malloc instead of using the default high-speed pool)
> instead of changing the internal implementation of one.
> 
> I promise to look closely at any patch you develop and make a
> recommendation to those with final approval rights.
> 
> Regards,
> Loren

Hi Loren,

I made a patch that addresses to first of the mentioned problems.
The patch is relative to a recent version of the 3.1 CVS source tree.

I discovered that Benjamin Kosnik already made one of the changes
that I proposed to ios_base::Init::Init (2001-07-03, change log says:
src/ios.cc (ios_base::Init::Init): Increment _S_ios_base_init last.)

I rethought the problem more carefully (now that I had to write a patch ;)
and came to the conclusion that it is not possible to make _S_ios_create
recursive when an ios_base::Init::Init object is being created inside
operator new; it leads to an infinite loop that can not be broken
except when we use detailed filebuf internal information inside _S_ios_create,
and that would not be very object oriented.

That means that instead of creating an ios_base::Init::Init object
inside operator new (in order to use std streams), the operator new
should test whether or not the std streams are already initialized
and not use them until they are.

In order to allow this I've added an accessor to class ios_base::Init::Init.

The attached patch contains a ChangeLog entry and a testsuite test that
check if the intended use of this new accessor does what it is supposed
to do.

Please tell me if you want to have functions/variables renamed, comments
added/removed, files moved etc.

-- 
Carlo Wood <carlo@alinoe.com>
Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/ChangeLog,v
retrieving revision 1.809
diff -u -d -p -r1.809 ChangeLog
--- ChangeLog	2001/10/13 00:06:20	1.809
+++ ChangeLog	2001/10/17 14:10:36
@@ -1,3 +1,9 @@
+2001-10-16  Carlo Wood  <carlo@alinoe.com>
+
+	* include/bits/ios_base.h(ios_base::Init::_S_initialized()): Added
+	_S_initialized() in order to allow debugging libraries to detect
+	when the std streams are initialized from an overloaded operator new.
+
 2001-10-12  Loren J. Rittle  <ljrittle@acm.org>
 
 	* docs/html/faq/index.html (Is libstdc++-v3 thread-safe?): Update
Index: include/bits/ios_base.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/ios_base.h,v
retrieving revision 1.13
diff -u -d -p -r1.13 ios_base.h
--- ios_base.h	2001/09/25 23:51:17	1.13
+++ ios_base.h	2001/10/17 14:10:37
@@ -301,6 +301,13 @@ namespace std
       static void
       _S_ios_destroy();
 
+      // _S_initialized() is an extension to allow debugger applications
+      // to use the standard streams from operator new.  _S_ios_base_init
+      // must be incremented in _S_ios_create _after_ initialization is
+      // completed.
+      static bool
+      _S_initialized() { return _S_ios_base_init; }
+
     private:
       static int 	_S_ios_base_init;
       static bool	_S_synced_with_stdio;
Index: testsuite/27_io/ios_init_initialized.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/ios_init_initialized.cc,v
diff -u -d -p -N /dev/null testsuite/27_io/ios_init_initialized.cc
--- /dev/null	Thu Aug 24 11:00:32 2000
+++ testsuite/27_io/ios_init_initialized.cc	Wed Oct 17 16:47:44 2001
@@ -0,0 +1,70 @@
+// 2001-10-17 Carlo Wood  <carlo@alinoe.com>
+
+// Copyright (C) 2001 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+// 27.4.2.1.6 class ios_base::init
+// This tests the extension _S_initialized().
+
+#include <iostream>
+#include <testsuite_hooks.h>
+#include <unistd.h>
+
+static int _S_initialized_count = 0;
+static int _S_uninitialized_count = 0;
+
+void* operator new(size_t size)
+{
+  static bool _S_internal = false;
+  if (std::ios_base::Init::_S_initialized())
+  {
+    if (size == 12345)
+      ++_S_initialized_count;
+    if (!_S_internal)
+    {
+      _S_internal = true;
+      std::cout << "Calling operator new(" << size << ")\n";
+      _S_internal = false;
+    }
+  }
+  else
+    ++_S_uninitialized_count;
+  return malloc(size);
+}
+ 
+int main(void)
+{
+  VERIFY( _S_uninitialized_count > 4 );
+  int uninitialized_count = _S_uninitialized_count;
+  _S_initialized_count = 0;
+  char* p = new char [12345];
+  delete [] p;
+  VERIFY( _S_initialized_count == 1 );
+  VERIFY( _S_uninitialized_count == uninitialized_count );
+  return 0;
+}
+

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