[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

memory.hxx
1/************************************************************************/
2/* */
3/* Copyright 2002-2003 by Ullrich Koethe, Hans Meine */
4/* */
5/* This file is part of the VIGRA computer vision library. */
6/* The VIGRA Website is */
7/* http://hci.iwr.uni-heidelberg.de/vigra/ */
8/* Please direct questions, bug reports, and contributions to */
9/* ullrich.koethe@iwr.uni-heidelberg.de or */
10/* vigra@informatik.uni-hamburg.de */
11/* */
12/* Permission is hereby granted, free of charge, to any person */
13/* obtaining a copy of this software and associated documentation */
14/* files (the "Software"), to deal in the Software without */
15/* restriction, including without limitation the rights to use, */
16/* copy, modify, merge, publish, distribute, sublicense, and/or */
17/* sell copies of the Software, and to permit persons to whom the */
18/* Software is furnished to do so, subject to the following */
19/* conditions: */
20/* */
21/* The above copyright notice and this permission notice shall be */
22/* included in all copies or substantial portions of the */
23/* Software. */
24/* */
25/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32/* OTHER DEALINGS IN THE SOFTWARE. */
33/* */
34/************************************************************************/
35
36#ifndef VIGRA_MEMORY_HXX
37#define VIGRA_MEMORY_HXX
38
39
40#include "config.hxx"
41
42#ifdef VIGRA_SHARED_PTR_IN_TR1
43# include <tr1/memory>
44#else
45# include <memory>
46#endif
47
48#include <cstring>
49#include "metaprogramming.hxx"
50
51namespace vigra {
52
53enum SkipInitializationTag { SkipInitialization};
54
55template<class T>
56struct CanSkipInitialization
57{
58 typedef typename TypeTraits<T>::isBuiltinType type;
59 static const bool value = type::asBool;
60};
61
62namespace detail {
63
64// differs from std::uninitialized_copy by explicit type conversion
65template <class Src, class Dest>
66Dest uninitializedCopy(Src s, Src end, Dest d)
67{
68 typedef typename std::iterator_traits<Dest>::value_type T;
69 for(; s != end; ++s, ++d)
70 new(d) T(static_cast<T const &>(*s));
71 return d;
72}
73
74template <class T>
75struct PlacementNewAllocator
76{
77 T * allocate(std::size_t n)
78 {
79 return (T*)::operator new(n*sizeof(T));
80 }
81
82 void deallocate(T * p, std::size_t)
83 {
84 return ::operator delete(p);
85 }
86
87 void construct(T * p, T const & initial)
88 {
89 new(p) T(initial);
90 }
91
92 void destroy(T * p)
93 {
94 p->~T();
95 }
96};
97
98template <class T>
99inline void
100destroy_n(T * /* p */, std::size_t /* n */, VigraTrueType /* isPOD */)
101{}
102
103template <class T>
104inline void
105destroy_n(T * p, std::size_t n, VigraFalseType /* isPOD */)
106{
107 for(std::size_t i=0; i < n; ++i, ++p)
108 p->~T();
109}
110
111template <class T>
112inline void
113destroy_n(T * p, std::size_t n)
114{
115 destroy_n(p, n, typename TypeTraits<T>::isPOD());
116}
117
118template <class T, class Alloc>
119inline T *
120alloc_initialize_n(std::size_t n, T const & initial, Alloc & alloc)
121{
122 T * p = alloc.allocate(n);
123 bool useMemset = TypeTraits<T>::isPOD::value &&
124 (initial == T());
125 if(useMemset)
126 {
127 std::memset(p, 0, n*sizeof(T));
128 }
129 else
130 {
131 std::size_t i=0;
132 try
133 {
134 for (; i < n; ++i) {
135#if (__cplusplus >= 202002L) || (defined(_MSC_VER) && _MSVC_LANG >= 202002L)
136 std::construct_at(p+i, initial); // from c++20
137#else
138 alloc.construct(p+i, initial); // until c++20
139#endif
140 }
141 }
142 catch (...)
143 {
144 for (std::size_t j=0; j < i; ++j) {
145#if (__cplusplus >= 202002L) || (defined(_MSC_VER) && _MSVC_LANG >= 202002L)
146 std::destroy_at(p+j); // from c++20
147#else
148 alloc.destroy(p+j); // until c++20
149#endif
150 }
151 alloc.deallocate(p, n);
152 throw;
153 }
154 }
155 return p;
156}
157
158template <class T>
159inline T *
160alloc_initialize_n(std::size_t n, T const & initial)
161{
162 PlacementNewAllocator<T> alloc;
163 return alloc_initialize_n<T>(n, initial, alloc);
164}
165
166template <class T>
167inline T *
168alloc_initialize_n(std::size_t n)
169{
170 PlacementNewAllocator<T> alloc;
171 return alloc_initialize_n<T>(n, T(), alloc);
172}
173
174template <class T, class Alloc>
175inline void
176destroy_dealloc_impl(T * p, std::size_t n, Alloc & alloc, VigraTrueType /* isPOD */)
177{
178 alloc.deallocate(p, n);
179}
180
181template <class T, class Alloc>
182inline void
183destroy_dealloc_impl(T * p, std::size_t n, Alloc & alloc, VigraFalseType /* isPOD */)
184{
185 for (std::size_t i=0; i < n; ++i) {
186#if (__cplusplus >= 202002L) || (defined(_MSC_VER) && _MSVC_LANG >= 202002L)
187 std::destroy_at(p + i);
188#else
189 alloc.destroy(p + i);
190#endif
191 }
192 alloc.deallocate(p, n);
193}
194
195template <class T, class Alloc>
196inline T *
197destroy_dealloc_n(T * p, std::size_t n, Alloc & alloc)
198{
199 if(p != 0)
200 destroy_dealloc_impl(p, n, alloc, typename TypeTraits<T>::isPOD());
201 return 0;
202}
203
204template <class T>
205inline T *
206destroy_dealloc_n(T * p, std::size_t n)
207{
208 if(p != 0)
209 {
210 PlacementNewAllocator<T> alloc;
211 destroy_dealloc_impl(p, n, alloc, typename TypeTraits<T>::isPOD());
212 }
213 return 0;
214}
215
216/********************************************************************/
217
218// g++ 2.95 has std::destroy() in the STL
219#if !defined(__GNUC__) || __GNUC__ >= 3
220
221template <class T>
222inline void destroy(T * /* p */, VigraTrueType /* isPOD */)
223{
224}
225
226template <class T>
227inline void destroy(T * p, VigraFalseType /* isPOD */)
228{
229 p->~T();
230}
231
232template <class T>
233inline void destroy(T * p)
234{
235 destroy(p, typename TypeTraits<T>::isPOD());
236}
237
238#else
239
240} } // namespace vigra::detail
241
242#include <memory>
243
244namespace vigra { namespace detail {
245
246using std::destroy;
247
248#endif
249
250} } // namespace vigra::detail
251
252#endif // VIGRA_MEMORY_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.12.2 (Mon Apr 14 2025)