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