1 /*****************************************************************************
2
3 AllocAlign.hpp
4 Author: Laurent de Soras, 2011
5
6 --- Legal stuff ---
7
8 This program is free software. It comes without any warranty, to
9 the extent permitted by applicable law. You can redistribute it
10 and/or modify it under the terms of the Do What The Fuck You Want
11 To Public License, Version 2, as published by Sam Hocevar. See
12 http://sam.zoy.org/wtfpl/COPYING for more details.
13
14 *Tab=3***********************************************************************/
15
16
17
18 #if ! defined (fstb_AllocAlign_CODEHEADER_INCLUDED)
19 #define fstb_AllocAlign_CODEHEADER_INCLUDED
20
21
22
23 /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
24
25 #include "fstb/def.h"
26
27 #include <cassert>
28 #if ! defined (_MSC_VER)
29 #include <cstdlib>
30 #endif
31
32
33
34 namespace fstb
35 {
36
37
38
39 /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
40
41
42
43 template <class T, long ALIG>
address(reference r)44 typename AllocAlign <T, ALIG>::pointer AllocAlign <T, ALIG>::address (reference r) noexcept
45 {
46 return &r;
47 }
48
49
50
51 template <class T, long ALIG>
address(const_reference r)52 typename AllocAlign <T, ALIG>::const_pointer AllocAlign <T, ALIG>::address (const_reference r) noexcept
53 {
54 return &r;
55 }
56
57
58
59 template <class T, long ALIG>
allocate(size_type n,const void * ptr)60 typename AllocAlign <T, ALIG>::pointer AllocAlign <T, ALIG>::allocate (size_type n, const void *ptr)
61 {
62 fstb::unused (ptr);
63 return allocate (n);
64 }
65
66
67
68 template <class T, long ALIG>
allocate(size_type n)69 typename AllocAlign <T, ALIG>::pointer AllocAlign <T, ALIG>::allocate (size_type n)
70 {
71 const size_t nbr_bytes = sizeof (T) * n;
72
73 #if defined (_MSC_VER)
74
75 pointer zone_ptr = static_cast <pointer> (
76 _aligned_malloc (nbr_bytes, ALIG)
77 );
78
79 //#elif ! defined (__MINGW32__) && ! defined (__MINGW64__) && ! defined (__CYGWIN__)
80 #elif (defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \
81 && ! defined (STM32H750xx)
82
83 pointer zone_ptr = nullptr;
84 void * tmp_ptr;
85 if (posix_memalign (&tmp_ptr, ALIG, nbr_bytes) == 0)
86 {
87 zone_ptr = reinterpret_cast <pointer> (tmp_ptr);
88 }
89
90 #else // Platform-independent implementation
91
92 const size_t ptr_size = sizeof (void *);
93 const size_t offset = ptr_size + ALIG - 1;
94 const size_t alloc_bytes = offset + nbr_bytes;
95 void * alloc_ptr = new char [alloc_bytes];
96 pointer zone_ptr = nullptr;
97 if (alloc_ptr != nullptr)
98 {
99 const intptr_t alloc_l = reinterpret_cast <intptr_t> (alloc_ptr);
100 const intptr_t zone_l = (alloc_l + offset) & (-ALIG);
101 assert (zone_l >= intptr_t (alloc_l + ptr_size));
102 void ** ptr_ptr = reinterpret_cast <void **> (zone_l - ptr_size);
103 *ptr_ptr = alloc_ptr;
104 zone_ptr = reinterpret_cast <pointer> (zone_l);
105 }
106
107 #endif
108
109 if (zone_ptr == nullptr)
110 {
111 #if defined (__cpp_exceptions) || ! defined (__GNUC__)
112 throw std::bad_alloc ();
113 #endif
114 }
115
116 return (zone_ptr);
117 }
118
119
120
121 template <class T, long ALIG>
deallocate(pointer ptr,size_type n)122 void AllocAlign <T, ALIG>::deallocate (pointer ptr, size_type n) noexcept
123 {
124 fstb::unused (n);
125
126 if (ptr != nullptr)
127 {
128
129 #if defined (_MSC_VER)
130
131 try
132 {
133 _aligned_free (ptr);
134 }
135 catch (...)
136 {
137 assert (false);
138 }
139
140 //#elif ! defined (__MINGW32__) && ! defined (__MINGW64__) && ! defined (__CYGWIN__)
141 #elif (defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \
142 && ! defined (STM32H750xx)
143
144 free (ptr);
145
146 #else // Platform-independent implementation
147
148 const size_t ptr_size = sizeof (void *);
149 const intptr_t zone_l = reinterpret_cast <intptr_t> (ptr);
150 void ** ptr_ptr = reinterpret_cast <void **> (zone_l - ptr_size);
151 void * alloc_ptr = *ptr_ptr;
152 assert (alloc_ptr != nullptr);
153 assert (reinterpret_cast <intptr_t> (alloc_ptr) < zone_l);
154
155 delete [] reinterpret_cast <char *> (alloc_ptr);
156
157 #endif
158 }
159 }
160
161
162
163 template <class T, long ALIG>
max_size() const164 typename AllocAlign <T, ALIG>::size_type AllocAlign <T, ALIG>::max_size () const noexcept
165 {
166 static_assert ((static_cast <size_type> (-1) > 0), "");
167
168 return (static_cast <size_type> (-1) / sizeof (T));
169 }
170
171
172
173 template <class T, long ALIG>
construct(pointer ptr,const T & t)174 void AllocAlign <T, ALIG>::construct (pointer ptr, const T &t)
175 {
176 assert (ptr != nullptr);
177
178 new (ptr) T (t);
179 }
180
181
182
183 template <class T, long ALIG>
destroy(pointer ptr)184 void AllocAlign <T, ALIG>::destroy (pointer ptr)
185 {
186 assert (ptr != nullptr);
187
188 ptr->~T ();
189 }
190
191
192
193 template <class T, long ALIG>
operator ==(AllocAlign<T,ALIG> const & other)194 bool AllocAlign <T, ALIG>::operator == (AllocAlign <T, ALIG> const &other) noexcept
195 {
196 fstb::unused (other);
197
198 return true;
199 }
200
201
202
203 template <class T, long ALIG>
operator !=(AllocAlign<T,ALIG> const & other)204 bool AllocAlign <T, ALIG>::operator != (AllocAlign <T, ALIG> const &other) noexcept
205 {
206 return (! operator == (other));
207 }
208
209
210
211 /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
212
213
214
215 /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
216
217
218
219 } // namespace fstb
220
221
222
223 #endif // fstb_AllocAlign_CODEHEADER_INCLUDED
224
225
226
227 /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
228