RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
AlignedAllocator.h
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2023 Roman Lebedev
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) 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 GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19*/
20
21#pragma once
22
23#include "adt/Invariant.h"
24#include "common/Common.h"
26#include <cassert>
27#include <cstddef>
28#include <cstdint>
29#include <cstdlib>
30#include <memory>
31#include <new>
32#include <type_traits>
33
34namespace rawspeed {
35
36template <class T, int alignment> class AlignedAllocator {
38 using allocator_traits = std::allocator_traits<self>;
39
40public:
41 using value_type = T;
42
43 template <class U> struct rebind final {
45 };
46
47 [[nodiscard]] T* allocate(std::size_t numElts) const {
48 static_assert(size_t(alignment) >= alignof(T), "insufficient alignment");
49 invariant(numElts > 0 && "Should not be trying to allocate no elements");
50 assert(numElts <= allocator_traits::max_size(*this) &&
51 "Can allocate this many elements.");
52 invariant(numElts <= SIZE_MAX / sizeof(T) &&
53 "Byte count calculation will not overflow");
54
55 std::size_t numBytes = sizeof(T) * numElts;
56
57#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
58 // workaround ASAN's broken allocator_may_return_null option
59 // plus, avoidance of libFuzzer's rss_limit_mb option
60 // if trying to alloc more than 2GB, just return null.
61 // else it would abort() the whole program...
62 if (numBytes > 2UL << 30UL)
63 ThrowRSE("FUZZ alloc bailout (%zu bytes)", numBytes);
64#endif
65
66 auto* r = static_cast<T*>(operator new(
67 numBytes, static_cast<std::align_val_t>(alignment)));
68 invariant(isAligned(r, alignment));
69 if (!r)
70 ThrowRSE("Out of memory while trying to allocate %zu bytes", numBytes);
71 return r;
72 }
73
74 void deallocate(T* p, std::size_t n) const noexcept {
75 invariant(p);
76 invariant(n > 0);
77 invariant(isAligned(p, alignment));
78 operator delete(p, static_cast<std::align_val_t>(alignment));
79 }
80
83 using propagate_on_container_swap = std::true_type;
84};
85
86template <class T1, int A1, class T2, int A2>
87bool operator==(const AlignedAllocator<T1, A1>& /*unused*/,
88 const AlignedAllocator<T2, A2>& /*unused*/) {
89 return A1 == A2;
90}
91
92template <class T1, int A1, class T2, int A2>
93bool operator!=(const AlignedAllocator<T1, A1>& /*unused*/,
94 const AlignedAllocator<T2, A2>& /*unused*/) {
95 return !(A1 == A2);
96}
97
98} // namespace rawspeed
#define invariant(expr)
Definition Invariant.h:27
#define ThrowRSE(...)
assert(dim.area() >=area)
std::allocator_traits< self > allocator_traits
void deallocate(T *p, std::size_t n) const noexcept
AlignedAllocator< T, alignment > self
T * allocate(std::size_t numElts) const
bool operator!=(const AlignedAllocator< T1, A1 > &, const AlignedAllocator< T2, A2 > &)
throw T(buf.data())
constexpr RAWSPEED_READNONE bool isAligned(T value, size_t multiple)
Definition Common.h:151
bool operator==(const AlignedAllocator< T1, A1 > &, const AlignedAllocator< T2, A2 > &)
AlignedAllocator< U, alignment > other