PLaSK library
Loading...
Searching...
No Matches
memalloc.hpp
Go to the documentation of this file.
1
/*
2
* This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3
* Copyright (c) 2022 Lodz University of Technology
4
*
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, version 3.
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*/
14
#ifndef PLASK__MEMALLOC_H
15
#define PLASK__MEMALLOC_H
16
17
#include <cstdlib>
18
#include <memory>
19
20
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
21
#include <malloc.h>
22
#endif
23
24
#include <utility>
25
#include <limits>
26
#include <new>
27
28
namespace
plask
{
29
30
#if (defined(__GLIBC__) && ((__GLIBC__>=2 && __GLIBC_MINOR__ >= 8) || __GLIBC__>2) && defined(__LP64__)) || \
31
defined(__APPLE__) || defined(_WIN64) || (defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__))
32
# define PLASK_MALLOC_ALIGNED 1
33
#else
34
# define PLASK_MALLOC_ALIGNED 0
35
#endif
36
37
38
#if !PLASK_MALLOC_ALIGNED && !defined(_MSC_VER)
39
namespace
detail {
40
44
inline
void
*
custom_aligned_malloc
(std::size_t size)
45
{
46
void
*original = std::malloc(size+16);
47
if
(original == 0)
return
0;
48
void
*
aligned
=
reinterpret_cast<
void
*
>
((
reinterpret_cast<
size_t
>
(original) & ~(
size_t
(15))) + 16);
49
*(
reinterpret_cast<
void
**
>
(
aligned
) - 1) = original;
50
return
aligned
;
51
}
52
56
inline
void
custom_aligned_free
(
void
*ptr)
57
{
58
if
(ptr) std::free(*(
reinterpret_cast<
void
**
>
(ptr) - 1));
59
}
60
64
inline
void
*
custom_aligned_realloc
(
void
* ptr, std::size_t size, std::size_t=0)
65
{
66
if
(ptr == 0)
return
custom_aligned_malloc
(size);
67
void
*original = *(
reinterpret_cast<
void
**
>
(ptr) - 1);
68
original = std::realloc(original,size+16);
69
if
(original == 0)
return
0;
70
void
*
aligned
=
reinterpret_cast<
void
*
>
((
reinterpret_cast<
size_t
>
(original) & ~(
size_t
(15))) + 16);
71
*(
reinterpret_cast<
void
**
>
(
aligned
) - 1) = original;
72
return
aligned
;
73
}
74
75
}
76
#endif
77
83
inline
void
*
aligned_malloc
(std::size_t size)
84
{
85
void
*
result
;
86
#if PLASK_MALLOC_ALIGNED
87
result
= std::malloc(size);
88
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
89
result
=
_aligned_malloc
(size, 16);
90
#else
91
result
=
detail::custom_aligned_malloc
(size);
92
#endif
93
if
(!
result
&& size)
throw
std::bad_alloc();
94
return
result
;
95
}
96
101
inline
void
aligned_free
(
void
*ptr)
102
{
103
if
(!ptr)
return
;
104
#if PLASK_MALLOC_ALIGNED
105
std::free(ptr);
106
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
107
_aligned_free
(ptr);
108
#else
109
detail::custom_aligned_free
(ptr);
110
#endif
111
}
112
120
inline
void
*
aligned_realloc
(
void
*ptr, std::size_t
new_size
, std::size_t
old_size
=0)
121
{
122
(
void
)
old_size
;
// don't warn about unused old_size
123
void
*
result
;
124
#if PLASK_MALLOC_ALIGNED
125
result
= std::realloc(ptr,
new_size
);
126
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
127
result
=
_aligned_realloc
(ptr,
new_size
,16);
128
#else
129
result
=
detail::custom_aligned_realloc
(ptr,
new_size
,
old_size
);
130
#endif
131
if
(!
result
&&
new_size
)
throw
std::bad_alloc();
132
return
result
;
133
}
134
141
template
<
typename
T>
142
inline
T*
aligned_malloc
(std::size_t num=1) {
143
T*
mem
=
reinterpret_cast<
T*
>
(
aligned_malloc
(num *
sizeof
(T)));
144
return
mem
;
145
}
146
152
template
<
typename
T>
153
inline
void
aligned_free
(T* ptr) {
154
aligned_free
(
reinterpret_cast<
void
*
>
(
const_cast<
typename
std::remove_const<T>::type*
>
(ptr)));
155
}
156
160
template
<
typename
T>
161
struct
aligned_deleter
{
162
constexpr
aligned_deleter
()
noexcept
=
default
;
163
template
<
typename
U,
typename
=
typename
std
::
enable_if
<
std
::
is_convertible
<U*,T*>::value>::type>
164
aligned_deleter
(
const
aligned_deleter
<U>&)
noexcept
{}
165
166
void
operator()
(T* ptr)
const
{
167
aligned_free<T>
(ptr);
168
}
169
};
170
171
template
<
class
T >
struct
aligned_deleter
<T[]> {
172
void
operator()
(T* ptr)
const
{
173
aligned_free<T>
(ptr);
174
}
175
};
176
177
template
<
typename
T>
178
using
aligned_unique_ptr
= std::unique_ptr<T, aligned_deleter<T>>;
179
186
template
<
typename
T,
typename
...
Args
>
187
inline
T*
aligned_new
(
Args
&&...
args
) {
188
T*
mem
=
reinterpret_cast<
T*
>
(
aligned_malloc
(
sizeof
(T)));
189
new
(
mem
) T(std::forward<Args>(
args
)...);
190
return
mem
;
191
}
192
198
template
<
typename
T>
199
inline
void
aligned_delete
(T* ptr) {
200
ptr->~T();
201
aligned_free
(ptr);
202
}
203
210
template
<
typename
T,
typename
...
Args
>
211
inline
T*
aligned_new_array
(std::size_t num,
Args
&&...
args
) {
212
T*
mem
=
reinterpret_cast<
T*
>
(
aligned_malloc
(num *
sizeof
(T)));
213
for
(
size_t
i = 0; i != num; ++i)
new
(
mem
+i) T(std::forward<Args>(
args
)...);
214
return
mem
;
215
}
216
223
template
<
typename
T>
224
inline
void
aligned_delete_array
(std::size_t num, T* ptr) {
225
while
(num)
226
ptr[--num].~T();
227
aligned_free
(ptr);
228
}
229
233
template
<
class
T>
234
struct
aligned_allocator
{
235
236
typedef
std::size_t
size_type
;
237
typedef
std::ptrdiff_t
difference_type
;
238
typedef
T*
pointer
;
239
typedef
const
T*
const_pointer
;
240
typedef
T&
reference
;
241
typedef
const
T&
const_reference
;
242
typedef
T
value_type
;
243
244
template
<
class
U>
245
struct
rebind
{
typedef
aligned_allocator<U>
other
; };
246
247
pointer
address
(
reference
value)
const
{
return
&value; }
248
249
const_pointer
address
(
const_reference
value)
const
{
return
&value; }
250
251
aligned_allocator
() {}
252
253
aligned_allocator
(
const
aligned_allocator
&) {}
254
255
template
<
class
U>
256
aligned_allocator
(
const
aligned_allocator<U>
&) {}
257
258
~aligned_allocator
(){}
259
260
size_type
max_size
()
const
{
return
(std::numeric_limits<size_type>::max)(); }
261
262
pointer
allocate
(
size_type
num) {
return
aligned_malloc<T>
(num); }
263
264
void
construct
(
pointer
p,
const
T& value) {
new
(p) T(value); }
265
266
template
<
typename
...
Args
>
267
void
construct
(
pointer
p,
Args
&&...
args
) {
new
(p) T(std::forward<Args>(
args
)...); }
268
269
void
destroy
(
pointer
p) { p->~T(); }
270
271
void
deallocate
(
pointer
p,
size_type
) {
aligned_free
(p); }
272
273
bool
operator!=
(
const
aligned_allocator<T>
&)
const
{
return
false
; }
274
275
bool
operator==
(
const
aligned_allocator<T>
&)
const
{
return
true
; }
276
};
277
278
279
280
}
// namespace plask
281
282
283
#endif
// PLASK__MEMALLOC_H
plask
memalloc.hpp
Generated by
1.9.8