Home | History | Annotate | Download | only in bits
      1 // Temporary buffer implementation -*- C++ -*-
      2 
      3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
      4 // 2010, 2011
      5 // Free Software Foundation, Inc.
      6 //
      7 // This file is part of the GNU ISO C++ Library.  This library is free
      8 // software; you can redistribute it and/or modify it under the
      9 // terms of the GNU General Public License as published by the
     10 // Free Software Foundation; either version 3, or (at your option)
     11 // any later version.
     12 
     13 // This library is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // Under Section 7 of GPL version 3, you are granted additional
     19 // permissions described in the GCC Runtime Library Exception, version
     20 // 3.1, as published by the Free Software Foundation.
     21 
     22 // You should have received a copy of the GNU General Public License and
     23 // a copy of the GCC Runtime Library Exception along with this program;
     24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25 // <http://www.gnu.org/licenses/>.
     26 
     27 /*
     28  *
     29  * Copyright (c) 1994
     30  * Hewlett-Packard Company
     31  *
     32  * Permission to use, copy, modify, distribute and sell this software
     33  * and its documentation for any purpose is hereby granted without fee,
     34  * provided that the above copyright notice appear in all copies and
     35  * that both that copyright notice and this permission notice appear
     36  * in supporting documentation.  Hewlett-Packard Company makes no
     37  * representations about the suitability of this software for any
     38  * purpose.  It is provided "as is" without express or implied warranty.
     39  *
     40  *
     41  * Copyright (c) 1996,1997
     42  * Silicon Graphics Computer Systems, Inc.
     43  *
     44  * Permission to use, copy, modify, distribute and sell this software
     45  * and its documentation for any purpose is hereby granted without fee,
     46  * provided that the above copyright notice appear in all copies and
     47  * that both that copyright notice and this permission notice appear
     48  * in supporting documentation.  Silicon Graphics makes no
     49  * representations about the suitability of this software for any
     50  * purpose.  It is provided "as is" without express or implied warranty.
     51  */
     52 
     53 /** @file bits/stl_tempbuf.h
     54  *  This is an internal header file, included by other library headers.
     55  *  Do not attempt to use it directly. @headername{memory}
     56  */
     57 
     58 #ifndef _STL_TEMPBUF_H
     59 #define _STL_TEMPBUF_H 1
     60 
     61 #include <bits/stl_algobase.h>
     62 #include <bits/stl_construct.h>
     63 
     64 namespace std _GLIBCXX_VISIBILITY(default)
     65 {
     66 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     67 
     68   /**
     69    *  @brief Allocates a temporary buffer.
     70    *  @param  __len  The number of objects of type Tp.
     71    *  @return See full description.
     72    *
     73    *  Reinventing the wheel, but this time with prettier spokes!
     74    *
     75    *  This function tries to obtain storage for @c __len adjacent Tp
     76    *  objects.  The objects themselves are not constructed, of course.
     77    *  A pair<> is returned containing <em>the buffer s address and
     78    *  capacity (in the units of sizeof(_Tp)), or a pair of 0 values if
     79    *  no storage can be obtained.</em>  Note that the capacity obtained
     80    *  may be less than that requested if the memory is unavailable;
     81    *  you should compare len with the .second return value.
     82    *
     83    * Provides the nothrow exception guarantee.
     84    */
     85   template<typename _Tp>
     86     pair<_Tp*, ptrdiff_t>
     87     get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT
     88     {
     89       const ptrdiff_t __max =
     90 	__gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
     91       if (__len > __max)
     92 	__len = __max;
     93 
     94       while (__len > 0)
     95 	{
     96 	  _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp),
     97 							std::nothrow));
     98 	  if (__tmp != 0)
     99 	    return std::pair<_Tp*, ptrdiff_t>(__tmp, __len);
    100 	  __len /= 2;
    101 	}
    102       return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0);
    103     }
    104 
    105   /**
    106    *  @brief The companion to get_temporary_buffer().
    107    *  @param  __p  A buffer previously allocated by get_temporary_buffer.
    108    *  @return   None.
    109    *
    110    *  Frees the memory pointed to by __p.
    111    */
    112   template<typename _Tp>
    113     inline void
    114     return_temporary_buffer(_Tp* __p)
    115     { ::operator delete(__p, std::nothrow); }
    116 
    117 
    118   /**
    119    *  This class is used in two places: stl_algo.h and ext/memory,
    120    *  where it is wrapped as the temporary_buffer class.  See
    121    *  temporary_buffer docs for more notes.
    122    */
    123   template<typename _ForwardIterator, typename _Tp>
    124     class _Temporary_buffer
    125     {
    126       // concept requirements
    127       __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept)
    128 
    129     public:
    130       typedef _Tp         value_type;
    131       typedef value_type* pointer;
    132       typedef pointer     iterator;
    133       typedef ptrdiff_t   size_type;
    134 
    135     protected:
    136       size_type  _M_original_len;
    137       size_type  _M_len;
    138       pointer    _M_buffer;
    139 
    140     public:
    141       /// As per Table mumble.
    142       size_type
    143       size() const
    144       { return _M_len; }
    145 
    146       /// Returns the size requested by the constructor; may be >size().
    147       size_type
    148       requested_size() const
    149       { return _M_original_len; }
    150 
    151       /// As per Table mumble.
    152       iterator
    153       begin()
    154       { return _M_buffer; }
    155 
    156       /// As per Table mumble.
    157       iterator
    158       end()
    159       { return _M_buffer + _M_len; }
    160 
    161       /**
    162        * Constructs a temporary buffer of a size somewhere between
    163        * zero and the size of the given range.
    164        */
    165       _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last);
    166 
    167       ~_Temporary_buffer()
    168       {
    169 	std::_Destroy(_M_buffer, _M_buffer + _M_len);
    170 	std::return_temporary_buffer(_M_buffer);
    171       }
    172 
    173     private:
    174       // Disable copy constructor and assignment operator.
    175       _Temporary_buffer(const _Temporary_buffer&);
    176 
    177       void
    178       operator=(const _Temporary_buffer&);
    179     };
    180 
    181 
    182   template<bool>
    183     struct __uninitialized_construct_buf_dispatch
    184     {
    185       template<typename _ForwardIterator, typename _Tp>
    186         static void
    187         __ucr(_ForwardIterator __first, _ForwardIterator __last,
    188 	      _Tp& __value)
    189         {
    190 	  if(__first == __last)
    191 	    return;
    192 
    193 	  _ForwardIterator __cur = __first;
    194 	  __try
    195 	    {
    196 	      std::_Construct(std::__addressof(*__first),
    197 			      _GLIBCXX_MOVE(__value));
    198 	      _ForwardIterator __prev = __cur;
    199 	      ++__cur;
    200 	      for(; __cur != __last; ++__cur, ++__prev)
    201 		std::_Construct(std::__addressof(*__cur),
    202 				_GLIBCXX_MOVE(*__prev));
    203 	      __value = _GLIBCXX_MOVE(*__prev);
    204 	    }
    205 	  __catch(...)
    206 	    {
    207 	      std::_Destroy(__first, __cur);
    208 	      __throw_exception_again;
    209 	    }
    210 	}
    211     };
    212 
    213   template<>
    214     struct __uninitialized_construct_buf_dispatch<true>
    215     {
    216       template<typename _ForwardIterator, typename _Tp>
    217         static void
    218         __ucr(_ForwardIterator, _ForwardIterator, _Tp&) { }
    219     };
    220 
    221   // Constructs objects in the range [first, last).
    222   // Note that while these new objects will take valid values,
    223   // their exact value is not defined. In particular they may
    224   // be 'moved from'.
    225   //
    226   // While __value may altered during this algorithm, it will have
    227   // the same value when the algorithm finishes, unless one of the
    228   // constructions throws.
    229   //
    230   // Requirements: _ForwardIterator::value_type(_Tp&&) is valid.
    231   template<typename _ForwardIterator, typename _Tp>
    232     inline void
    233     __uninitialized_construct_buf(_ForwardIterator __first,
    234 				  _ForwardIterator __last,
    235 				  _Tp& __value)
    236     {
    237       typedef typename std::iterator_traits<_ForwardIterator>::value_type
    238 	_ValueType;
    239 
    240       std::__uninitialized_construct_buf_dispatch<
    241         __has_trivial_constructor(_ValueType)>::
    242 	  __ucr(__first, __last, __value);
    243     }
    244 
    245   template<typename _ForwardIterator, typename _Tp>
    246     _Temporary_buffer<_ForwardIterator, _Tp>::
    247     _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last)
    248     : _M_original_len(std::distance(__first, __last)),
    249       _M_len(0), _M_buffer(0)
    250     {
    251       __try
    252 	{
    253 	  std::pair<pointer, size_type> __p(std::get_temporary_buffer<
    254 					    value_type>(_M_original_len));
    255 	  _M_buffer = __p.first;
    256 	  _M_len = __p.second;
    257 	  if(_M_buffer)
    258 	    std::__uninitialized_construct_buf(_M_buffer, _M_buffer + _M_len,
    259 					       *__first);
    260 	}
    261       __catch(...)
    262 	{
    263 	  std::return_temporary_buffer(_M_buffer);
    264 	  _M_buffer = 0;
    265 	  _M_len = 0;
    266 	  __throw_exception_again;
    267 	}
    268     }
    269 
    270 _GLIBCXX_END_NAMESPACE_VERSION
    271 } // namespace
    272 
    273 #endif /* _STL_TEMPBUF_H */
    274 
    275