/ src / ios_init.cc
ios_init.cc
  1  // Iostreams base classes -*- C++ -*-
  2  
  3  // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
  4  // Free Software Foundation, Inc.
  5  //
  6  // This file is part of the GNU ISO C++ Library.  This library is free
  7  // software; you can redistribute it and/or modify it under the
  8  // terms of the GNU General Public License as published by the
  9  // Free Software Foundation; either version 2, or (at your option)
 10  // any later version.
 11  
 12  // This library is distributed in the hope that it will be useful,
 13  // but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  // GNU General Public License for more details.
 16  
 17  // You should have received a copy of the GNU General Public License along
 18  // with this library; see the file COPYING.  If not, write to the Free
 19  // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 20  // USA.
 21  
 22  // As a special exception, you may use this file as part of a free software
 23  // library without restriction.  Specifically, if other files instantiate
 24  // templates or use macros or inline functions from this file, or you compile
 25  // this file and link it with other files to produce an executable, this
 26  // file does not by itself cause the resulting executable to be covered by
 27  // the GNU General Public License.  This exception does not however
 28  // invalidate any other reasons why the executable file might be covered by
 29  // the GNU General Public License.
 30  
 31  //
 32  // ISO C++ 14882: 27.4  Iostreams base classes
 33  //
 34  
 35  #include <ios>
 36  #include <ostream>
 37  #include <istream>
 38  #include <fstream>
 39  #include <ext/stdio_filebuf.h>
 40  #include <ext/stdio_sync_filebuf.h>
 41  
 42  namespace __gnu_internal _GLIBCXX_VISIBILITY(hidden)
 43  {
 44    using namespace __gnu_cxx;
 45  
 46    // Extern declarations for global objects in src/globals.cc.
 47    extern stdio_sync_filebuf<char> buf_cout_sync;
 48    extern stdio_sync_filebuf<char> buf_cin_sync;
 49    extern stdio_sync_filebuf<char> buf_cerr_sync;
 50  
 51    extern stdio_filebuf<char> buf_cout;
 52    extern stdio_filebuf<char> buf_cin;
 53    extern stdio_filebuf<char> buf_cerr;
 54  
 55  #ifdef _GLIBCXX_USE_WCHAR_T
 56    extern stdio_sync_filebuf<wchar_t> buf_wcout_sync;
 57    extern stdio_sync_filebuf<wchar_t> buf_wcin_sync;
 58    extern stdio_sync_filebuf<wchar_t> buf_wcerr_sync;
 59  
 60    extern stdio_filebuf<wchar_t> buf_wcout;
 61    extern stdio_filebuf<wchar_t> buf_wcin;
 62    extern stdio_filebuf<wchar_t> buf_wcerr;
 63  #endif
 64  } // namespace __gnu_internal
 65  
 66  _GLIBCXX_BEGIN_NAMESPACE(std)
 67  
 68    using namespace __gnu_internal;
 69    
 70    extern istream cin;
 71    extern ostream cout;
 72    extern ostream cerr;
 73    extern ostream clog;
 74  
 75  #ifdef _GLIBCXX_USE_WCHAR_T
 76    extern wistream wcin;
 77    extern wostream wcout;
 78    extern wostream wcerr;
 79    extern wostream wclog;
 80  #endif
 81  
 82  static
 83  pthread_mutex_t&
 84  get_mut()
 85  {
 86      static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
 87      return mut;
 88  }
 89  
 90  ios_base::Init::Init()
 91  {
 92      if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, 0) == 0)
 93      {
 94          // If _S_refcount looks like 0, we need to lock a mutex
 95          pthread_mutex_lock(&get_mut());
 96          // If _S_refcount is still 0, then initialize
 97          if (_S_refcount == 0)
 98          {
 99              try
100              {
101                  // Standard streams default to synced with "C" operations.
102                  _S_synced_with_stdio = true;
103                  
104                  new (&buf_cout_sync) stdio_sync_filebuf<char>(stdout);
105                  new (&buf_cin_sync) stdio_sync_filebuf<char>(stdin);
106                  new (&buf_cerr_sync) stdio_sync_filebuf<char>(stderr);
107                  
108                  // The standard streams are constructed once only and never
109                  // destroyed.
110                  new (&cout) ostream(&buf_cout_sync);
111                  new (&cin) istream(&buf_cin_sync);
112                  new (&cerr) ostream(&buf_cerr_sync);
113                  new (&clog) ostream(&buf_cerr_sync);
114                  cin.tie(&cout);
115                  cerr.flags(ios_base::unitbuf);
116                  // _GLIBCXX_RESOLVE_LIB_DEFECTS
117                  // 455. cerr::tie() and wcerr::tie() are overspecified.
118                  cerr.tie(&cout);
119  
120  #ifdef _GLIBCXX_USE_WCHAR_T
121                  new (&buf_wcout_sync) stdio_sync_filebuf<wchar_t>(stdout);
122                  new (&buf_wcin_sync) stdio_sync_filebuf<wchar_t>(stdin);
123                  new (&buf_wcerr_sync) stdio_sync_filebuf<wchar_t>(stderr);
124                  
125                  new (&wcout) wostream(&buf_wcout_sync);
126                  new (&wcin) wistream(&buf_wcin_sync);
127                  new (&wcerr) wostream(&buf_wcerr_sync);
128                  new (&wclog) wostream(&buf_wcerr_sync);
129                  wcin.tie(&wcout);
130                  wcerr.flags(ios_base::unitbuf);
131                  wcerr.tie(&wcout);    
132  #endif
133          
134                  _S_refcount = 2;
135              }
136              catch (...)
137              {
138                  pthread_mutex_unlock(&get_mut());
139                  throw;
140              }
141          }
142          else
143          // Else _S_refcount != 0 which means initialization is complete, else
144          //   I couldn't have gotten the mutex.
145              ++_S_refcount;
146          pthread_mutex_unlock(&get_mut());
147      }
148      else  // _S_refcount >= 2
149          __gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, 1);
150  }
151  
152    ios_base::Init::~Init()
153    {
154      if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, -1) == 2)
155        {
156  	// Catch any exceptions thrown by basic_ostream::flush()
157  	try
158  	  { 
159  	    // Flush standard output streams as required by 27.4.2.1.6
160  	    cout.flush();
161  	    cerr.flush();
162  	    clog.flush();
163      
164  #ifdef _GLIBCXX_USE_WCHAR_T
165  	    wcout.flush();
166  	    wcerr.flush();
167  	    wclog.flush();    
168  #endif
169  	  }
170  	catch (...)
171  	  { }
172        }
173    } 
174  
175    bool 
176    ios_base::sync_with_stdio(bool __sync)
177    { 
178      // _GLIBCXX_RESOLVE_LIB_DEFECTS
179      // 49.  Underspecification of ios_base::sync_with_stdio
180      bool __ret = ios_base::Init::_S_synced_with_stdio;
181  
182      // Turn off sync with C FILE* for cin, cout, cerr, clog iff
183      // currently synchronized.
184      if (!__sync && __ret)
185        {
186  	// Make sure the standard streams are constructed.
187  	ios_base::Init __init;
188  
189  	ios_base::Init::_S_synced_with_stdio = __sync;
190  
191  	// Explicitly call dtors to free any memory that is
192  	// dynamically allocated by filebuf ctor or member functions,
193  	// but don't deallocate all memory by calling operator delete.
194  	buf_cout_sync.~stdio_sync_filebuf<char>();
195  	buf_cin_sync.~stdio_sync_filebuf<char>();
196  	buf_cerr_sync.~stdio_sync_filebuf<char>();
197  
198  #ifdef _GLIBCXX_USE_WCHAR_T
199  	buf_wcout_sync.~stdio_sync_filebuf<wchar_t>();
200  	buf_wcin_sync.~stdio_sync_filebuf<wchar_t>();
201  	buf_wcerr_sync.~stdio_sync_filebuf<wchar_t>();
202  #endif
203  
204  	// Create stream buffers for the standard streams and use
205  	// those buffers without destroying and recreating the
206  	// streams.
207  	new (&buf_cout) stdio_filebuf<char>(stdout, ios_base::out);
208  	new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in);
209  	new (&buf_cerr) stdio_filebuf<char>(stderr, ios_base::out);
210  	cout.rdbuf(&buf_cout);
211  	cin.rdbuf(&buf_cin);
212  	cerr.rdbuf(&buf_cerr);
213  	clog.rdbuf(&buf_cerr);
214      
215  #ifdef _GLIBCXX_USE_WCHAR_T
216  	new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out);
217  	new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in);
218  	new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out);
219  	wcout.rdbuf(&buf_wcout);
220  	wcin.rdbuf(&buf_wcin);
221  	wcerr.rdbuf(&buf_wcerr);
222  	wclog.rdbuf(&buf_wcerr);
223  #endif
224        }
225      return __ret; 
226    }
227  
228  _GLIBCXX_END_NAMESPACE