libstdc++
stl_tempbuf.h
Go to the documentation of this file.
1 // Temporary buffer implementation -*- C++ -*-
2 
3 // Copyright (C) 2001-2026 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /*
26  *
27  * Copyright (c) 1994
28  * Hewlett-Packard Company
29  *
30  * Permission to use, copy, modify, distribute and sell this software
31  * and its documentation for any purpose is hereby granted without fee,
32  * provided that the above copyright notice appear in all copies and
33  * that both that copyright notice and this permission notice appear
34  * in supporting documentation. Hewlett-Packard Company makes no
35  * representations about the suitability of this software for any
36  * purpose. It is provided "as is" without express or implied warranty.
37  *
38  *
39  * Copyright (c) 1996,1997
40  * Silicon Graphics Computer Systems, Inc.
41  *
42  * Permission to use, copy, modify, distribute and sell this software
43  * and its documentation for any purpose is hereby granted without fee,
44  * provided that the above copyright notice appear in all copies and
45  * that both that copyright notice and this permission notice appear
46  * in supporting documentation. Silicon Graphics makes no
47  * representations about the suitability of this software for any
48  * purpose. It is provided "as is" without express or implied warranty.
49  */
50 
51 /** @file bits/stl_tempbuf.h
52  * This is an internal header file, included by other library headers.
53  * Do not attempt to use it directly. @headername{memory}
54  */
55 
56 #ifndef _STL_TEMPBUF_H
57 #define _STL_TEMPBUF_H 1
58 
59 #include <new>
60 #include <bits/exception_defines.h>
61 #include <bits/stl_construct.h>
62 #include <bits/stl_pair.h>
63 #include <ext/numeric_traits.h>
64 
65 namespace std _GLIBCXX_VISIBILITY(default)
66 {
67 _GLIBCXX_BEGIN_NAMESPACE_VERSION
68 
69 #if __has_builtin(__builtin_operator_new) >= 201802L
70 # define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
71 # define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
72 #else
73 # define _GLIBCXX_OPERATOR_NEW ::operator new
74 # define _GLIBCXX_OPERATOR_DELETE ::operator delete
75 #endif
76 
77  namespace __detail
78  {
79  // Equivalent to std::get_temporary_buffer but won't return a smaller size.
80  // It either returns a buffer of __len elements, or a null pointer.
81  template<typename _Tp>
82  inline _Tp*
83  __get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOTHROW
84  {
85  if (__builtin_expect(size_t(__len) > (size_t(-1) / sizeof(_Tp)), 0))
86  return 0;
87 
88 #if __cpp_aligned_new && __cplusplus >= 201103L
89  if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
90  return (_Tp*) _GLIBCXX_OPERATOR_NEW(__len * sizeof(_Tp),
91  align_val_t(alignof(_Tp)),
92  nothrow_t());
93 #endif
94  return (_Tp*) _GLIBCXX_OPERATOR_NEW(__len * sizeof(_Tp), nothrow_t());
95  }
96 
97  // Equivalent to std::return_temporary_buffer but with a size argument.
98  // The size is the number of elements, not the number of bytes.
99  template<typename _Tp>
100  inline void
101  __return_temporary_buffer(_Tp* __p,
102  size_t __len __attribute__((__unused__)))
103  {
104 #if __cpp_sized_deallocation
105 # define _GLIBCXX_SIZED_DEALLOC(T, p, n) (p), (n) * sizeof(T)
106 #else
107 # define _GLIBCXX_SIZED_DEALLOC(T, p, n) (p)
108 #endif
109 
110 #if __cpp_aligned_new && __cplusplus >= 201103L
111  if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
112  {
113  _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(_Tp, __p, __len),
114  align_val_t(alignof(_Tp)));
115  return;
116  }
117 #endif
118  _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(_Tp, __p, __len));
119  }
120 #undef _GLIBCXX_SIZED_DEALLOC
121  }
122 
123  /**
124  * @brief Allocates a temporary buffer.
125  * @param __len The number of objects of type Tp.
126  * @return See full description.
127  *
128  * Reinventing the wheel, but this time with prettier spokes!
129  *
130  * This function tries to obtain storage for @c __len adjacent Tp
131  * objects. The objects themselves are not constructed, of course.
132  * A pair<> is returned containing <em>the buffer's address and
133  * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if
134  * no storage can be obtained.</em> Note that the capacity obtained
135  * may be less than that requested if the memory is unavailable;
136  * you should compare len with the .second return value.
137  *
138  * Provides the nothrow exception guarantee.
139  */
140  template<typename _Tp>
141  _GLIBCXX17_DEPRECATED
142  pair<_Tp*, ptrdiff_t>
143  get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT
144  {
145  const ptrdiff_t __max =
146  __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
147  if (__len > __max)
148  __len = __max;
149 
150  while (__len > 0)
151  {
152  if (_Tp* __tmp = __detail::__get_temporary_buffer<_Tp>(__len))
153  return pair<_Tp*, ptrdiff_t>(__tmp, __len);
154  __len = __len == 1 ? 0 : ((__len + 1) / 2);
155  }
156  return pair<_Tp*, ptrdiff_t>();
157  }
158 
159  /**
160  * @brief The companion to get_temporary_buffer().
161  * @param __p A buffer previously allocated by get_temporary_buffer.
162  *
163  * Frees the memory pointed to by __p.
164  */
165  template<typename _Tp>
166  _GLIBCXX17_DEPRECATED
167  inline void
169  {
170 #if __cpp_aligned_new && __cplusplus >= 201103L
171  if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
172  _GLIBCXX_OPERATOR_DELETE(__p, align_val_t(alignof(_Tp)));
173  else
174 #endif
175  _GLIBCXX_OPERATOR_DELETE(__p);
176  }
177 
178 #undef _GLIBCXX_OPERATOR_DELETE
179 #undef _GLIBCXX_OPERATOR_NEW
180 
181  /**
182  * This class is used in two places: stl_algo.h and ext/memory,
183  * where it is wrapped as the temporary_buffer class. See
184  * temporary_buffer docs for more notes.
185  */
186  template<typename _ForwardIterator, typename _Tp>
188  {
189  // concept requirements
190  __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept)
191 
192  public:
193  typedef _Tp value_type;
194  typedef value_type* pointer;
195  typedef pointer iterator;
196  typedef ptrdiff_t size_type;
197 
198  protected:
199  size_type _M_original_len;
200  struct _Impl
201  {
202 #pragma GCC diagnostic push
203 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
204  explicit
205  _Impl(ptrdiff_t __original_len)
206  {
208  std::get_temporary_buffer<value_type>(__original_len));
209  _M_len = __p.second;
210  _M_buffer = __p.first;
211  }
212 #pragma GCC diagnostic pop
213 
214  ~_Impl()
215  { std::__detail::__return_temporary_buffer(_M_buffer, _M_len); }
216 
217  size_type _M_len;
218  pointer _M_buffer;
219  } _M_impl;
220 
221  public:
222  /// As per Table mumble.
223  size_type
224  size() const
225  { return _M_impl._M_len; }
226 
227  /// Returns the size requested by the constructor; may be >size().
228  size_type
230  { return _M_original_len; }
231 
232  /// As per Table mumble.
233  iterator
235  { return _M_impl._M_buffer; }
236 
237  /// As per Table mumble.
238  iterator
239  end()
240  { return _M_impl._M_buffer + _M_impl._M_len; }
241 
242  /**
243  * Constructs a temporary buffer of a size somewhere between
244  * zero and the given length.
245  */
246  _Temporary_buffer(_ForwardIterator __seed, size_type __original_len);
247 
249  { std::_Destroy(_M_impl._M_buffer, _M_impl._M_buffer + _M_impl._M_len); }
250 
251  private:
252  // Disable copy constructor and assignment operator.
254 
255  void
256  operator=(const _Temporary_buffer&);
257  };
258 
259 
260  template<bool>
261  struct __uninitialized_construct_buf_dispatch
262  {
263  template<typename _Pointer, typename _ForwardIterator>
264  static void
265  __ucr(_Pointer __first, _Pointer __last,
266  _ForwardIterator __seed)
267  {
268  if (__builtin_expect(__first == __last, 0))
269  return;
270 
271  _Pointer __cur = __first;
272  __try
273  {
275  _GLIBCXX_MOVE(*__seed));
276  _Pointer __prev = __cur;
277  ++__cur;
278  for(; __cur != __last; ++__cur, ++__prev)
280  _GLIBCXX_MOVE(*__prev));
281  *__seed = _GLIBCXX_MOVE(*__prev);
282  }
283  __catch(...)
284  {
285  std::_Destroy(__first, __cur);
286  __throw_exception_again;
287  }
288  }
289  };
290 
291  template<>
292  struct __uninitialized_construct_buf_dispatch<true>
293  {
294  template<typename _Pointer, typename _ForwardIterator>
295  static void
296  __ucr(_Pointer, _Pointer, _ForwardIterator) { }
297  };
298 
299  // Constructs objects in the range [first, last).
300  // Note that while these new objects will take valid values,
301  // their exact value is not defined. In particular they may
302  // be 'moved from'.
303  //
304  // While *__seed may be altered during this algorithm, it will have
305  // the same value when the algorithm finishes, unless one of the
306  // constructions throws.
307  //
308  // Requirements:
309  // _Tp is move constructible and constructible from std::move(*__seed).
310  template<typename _Tp, typename _ForwardIterator>
311  inline void
312  __uninitialized_construct_buf(_Tp* __first, _Tp* __last,
313  _ForwardIterator __seed)
314  {
315  std::__uninitialized_construct_buf_dispatch<
316  __has_trivial_constructor(_Tp)>::
317  __ucr(__first, __last, __seed);
318  }
319 
320  template<typename _ForwardIterator, typename _Tp>
322  _Temporary_buffer(_ForwardIterator __seed, size_type __original_len)
323  : _M_original_len(__original_len), _M_impl(__original_len)
324  {
325  std::__uninitialized_construct_buf(begin(), end(), __seed);
326  }
327 
328 _GLIBCXX_END_NAMESPACE_VERSION
329 } // namespace
330 
331 #endif /* _STL_TEMPBUF_H */
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:52
ISO C++ entities toplevel namespace is std.
void return_temporary_buffer(_Tp *__p)
The companion to get_temporary_buffer().
Definition: stl_tempbuf.h:168
constexpr void _Construct(_Tp *__p, _Args &&... __args)
constexpr void _Destroy(_ForwardIterator __first, _ForwardIterator __last)
pair< _Tp *, ptrdiff_t > get_temporary_buffer(ptrdiff_t __len) noexcept
Allocates a temporary buffer.
Definition: stl_tempbuf.h:143
Struct holding two objects (or references) of arbitrary type.
Definition: stl_pair.h:307
_T1 first
The first member.
Definition: stl_pair.h:311
_T2 second
The second member.
Definition: stl_pair.h:312
Common iterator class.
iterator end()
As per Table mumble.
Definition: stl_tempbuf.h:239
size_type size() const
As per Table mumble.
Definition: stl_tempbuf.h:224
iterator begin()
As per Table mumble.
Definition: stl_tempbuf.h:234
size_type _M_requested_size() const
Returns the size requested by the constructor; may be >size().
Definition: stl_tempbuf.h:229
_Temporary_buffer(_ForwardIterator __seed, size_type __original_len)
Definition: stl_tempbuf.h:322