libstdc++
stl_tempbuf.h
Go to the documentation of this file.
1 // Temporary buffer implementation -*- C++ -*-
2 
3 // Copyright (C) 2001-2025 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  * @return None.
163  *
164  * Frees the memory pointed to by __p.
165  */
166  template<typename _Tp>
167  _GLIBCXX17_DEPRECATED
168  inline void
170  {
171 #if __cpp_aligned_new && __cplusplus >= 201103L
172  if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
173  _GLIBCXX_OPERATOR_DELETE(__p, align_val_t(alignof(_Tp)));
174  else
175 #endif
176  _GLIBCXX_OPERATOR_DELETE(__p);
177  }
178 
179 #undef _GLIBCXX_OPERATOR_DELETE
180 #undef _GLIBCXX_OPERATOR_NEW
181 
182  /**
183  * This class is used in two places: stl_algo.h and ext/memory,
184  * where it is wrapped as the temporary_buffer class. See
185  * temporary_buffer docs for more notes.
186  */
187  template<typename _ForwardIterator, typename _Tp>
189  {
190  // concept requirements
191  __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept)
192 
193  public:
194  typedef _Tp value_type;
195  typedef value_type* pointer;
196  typedef pointer iterator;
197  typedef ptrdiff_t size_type;
198 
199  protected:
200  size_type _M_original_len;
201  struct _Impl
202  {
203 #pragma GCC diagnostic push
204 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
205  explicit
206  _Impl(ptrdiff_t __original_len)
207  {
209  std::get_temporary_buffer<value_type>(__original_len));
210  _M_len = __p.second;
211  _M_buffer = __p.first;
212  }
213 #pragma GCC diagnostic pop
214 
215  ~_Impl()
216  { std::__detail::__return_temporary_buffer(_M_buffer, _M_len); }
217 
218  size_type _M_len;
219  pointer _M_buffer;
220  } _M_impl;
221 
222  public:
223  /// As per Table mumble.
224  size_type
225  size() const
226  { return _M_impl._M_len; }
227 
228  /// Returns the size requested by the constructor; may be >size().
229  size_type
231  { return _M_original_len; }
232 
233  /// As per Table mumble.
234  iterator
236  { return _M_impl._M_buffer; }
237 
238  /// As per Table mumble.
239  iterator
240  end()
241  { return _M_impl._M_buffer + _M_impl._M_len; }
242 
243  /**
244  * Constructs a temporary buffer of a size somewhere between
245  * zero and the given length.
246  */
247  _Temporary_buffer(_ForwardIterator __seed, size_type __original_len);
248 
250  { std::_Destroy(_M_impl._M_buffer, _M_impl._M_buffer + _M_impl._M_len); }
251 
252  private:
253  // Disable copy constructor and assignment operator.
255 
256  void
257  operator=(const _Temporary_buffer&);
258  };
259 
260 
261  template<bool>
262  struct __uninitialized_construct_buf_dispatch
263  {
264  template<typename _Pointer, typename _ForwardIterator>
265  static void
266  __ucr(_Pointer __first, _Pointer __last,
267  _ForwardIterator __seed)
268  {
269  if (__builtin_expect(__first == __last, 0))
270  return;
271 
272  _Pointer __cur = __first;
273  __try
274  {
276  _GLIBCXX_MOVE(*__seed));
277  _Pointer __prev = __cur;
278  ++__cur;
279  for(; __cur != __last; ++__cur, ++__prev)
281  _GLIBCXX_MOVE(*__prev));
282  *__seed = _GLIBCXX_MOVE(*__prev);
283  }
284  __catch(...)
285  {
286  std::_Destroy(__first, __cur);
287  __throw_exception_again;
288  }
289  }
290  };
291 
292  template<>
293  struct __uninitialized_construct_buf_dispatch<true>
294  {
295  template<typename _Pointer, typename _ForwardIterator>
296  static void
297  __ucr(_Pointer, _Pointer, _ForwardIterator) { }
298  };
299 
300  // Constructs objects in the range [first, last).
301  // Note that while these new objects will take valid values,
302  // their exact value is not defined. In particular they may
303  // be 'moved from'.
304  //
305  // While *__seed may be altered during this algorithm, it will have
306  // the same value when the algorithm finishes, unless one of the
307  // constructions throws.
308  //
309  // Requirements:
310  // _Tp is move constructible and constructible from std::move(*__seed).
311  template<typename _Tp, typename _ForwardIterator>
312  inline void
313  __uninitialized_construct_buf(_Tp* __first, _Tp* __last,
314  _ForwardIterator __seed)
315  {
316  std::__uninitialized_construct_buf_dispatch<
317  __has_trivial_constructor(_Tp)>::
318  __ucr(__first, __last, __seed);
319  }
320 
321  template<typename _ForwardIterator, typename _Tp>
323  _Temporary_buffer(_ForwardIterator __seed, size_type __original_len)
324  : _M_original_len(__original_len), _M_impl(__original_len)
325  {
326  std::__uninitialized_construct_buf(begin(), end(), __seed);
327  }
328 
329 _GLIBCXX_END_NAMESPACE_VERSION
330 } // namespace
331 
332 #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:169
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 of arbitrary type.
Definition: stl_pair.h:304
_T1 first
The first member.
Definition: stl_pair.h:308
_T2 second
The second member.
Definition: stl_pair.h:309
Common iterator class.
iterator end()
As per Table mumble.
Definition: stl_tempbuf.h:240
size_type requested_size() const
Returns the size requested by the constructor; may be >size().
Definition: stl_tempbuf.h:230
size_type size() const
As per Table mumble.
Definition: stl_tempbuf.h:225
iterator begin()
As per Table mumble.
Definition: stl_tempbuf.h:235
_Temporary_buffer(_ForwardIterator __seed, size_type __original_len)
Definition: stl_tempbuf.h:323