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