1/*
2Copyright 2018 Google Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS-IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef RESONANCE_AUDIO_BASE_ALIGNED_ALLOCATOR_H_
18#define RESONANCE_AUDIO_BASE_ALIGNED_ALLOCATOR_H_
19
20#include <stdlib.h>
21
22#include <algorithm>
23#include <cstddef>
24#include <memory>
25#include <type_traits>
26
27#include "base/simd_utils.h"
28
29
30namespace vraudio {
31
32// Performs static assert checks on the types size and alignment parameters.
33template <size_t TypeSize, size_t Alignment>
34void StaticAlignmentCheck() {
35 const bool alignment_is_power_of_two =
36 !(Alignment == 0) && !(Alignment & (Alignment - 1));
37 static_assert(alignment_is_power_of_two, "Alignment must be power of two");
38
39 const bool type_size_is_power_of_two = !(TypeSize & (TypeSize - 1));
40 static_assert(type_size_is_power_of_two, "Type size must be power of two");
41}
42
43// Returns a pointer to aligned memory.
44template <typename Type, typename SizeType, typename PointerType>
45PointerType AllignedMalloc(SizeType size, SizeType alignment) {
46 const SizeType data_size = size * sizeof(Type);
47 const SizeType offset = alignment - 1 + sizeof(PointerType);
48 void* mem_block_begin = malloc(data_size + offset);
49 if (mem_block_begin == nullptr) {
50 return nullptr;
51 }
52 // Find memory aligned address.
53 void** mem_block_aligned = reinterpret_cast<void**>(
54 ((reinterpret_cast<SizeType>(mem_block_begin) + offset) &
55 (~(alignment - 1))));
56 // Save pointer to original block right before the aligned block.
57 mem_block_aligned[-1] = mem_block_begin;
58 return reinterpret_cast<PointerType>(mem_block_aligned);
59}
60
61// Frees memory that has been aligned with |AllignedMalloc|.
62template <typename PointerType>
63void AllignedFree(PointerType mem_block_aligned) {
64 free(ptr: *(reinterpret_cast<void**>(mem_block_aligned) - 1));
65}
66
67// Class that allocates aligned memory. It is derived from std::allocator class
68// to be used with STL containers.
69//
70// @tparam Type Datatype of container to allocate.
71// @tparam Alignment Size of memory alignment.
72template <typename Type, size_t Alignment>
73class AlignedAllocator : public std::allocator<Type> {
74 public:
75 using Pointer = typename std::allocator_traits<std::allocator<Type>>::pointer;
76 using ConstPointer = typename std::allocator_traits<std::allocator<Type>>::const_pointer;
77 using SizeType = typename std::allocator_traits<std::allocator<Type>>::size_type;
78
79 AlignedAllocator() { StaticAlignmentCheck<sizeof(Type), Alignment>(); }
80
81 // Allocates memory for |size| elements and returns a pointer that is aligned
82 // to a multiple to |Alignment|.
83 //
84 // @param size Number of elements to allocate.
85 // @return Returns memory aligned pointer.
86 Pointer allocate(SizeType size) { return allocate(size, nullptr); }
87
88 // Allocates memory for |size| elements and returns a pointer that is aligned
89 // to a multiple to |Alignment|.
90 //
91 // @param size Number of elements to allocate.
92 // @return Returns memory aligned pointer.
93 Pointer allocate(SizeType size, ConstPointer /* hint */) {
94
95 return AllignedMalloc<Type, SizeType, Pointer>(size, Alignment);
96 }
97
98 void deallocate(Pointer mem_block_aligned, size_t size) {
99 AllignedFree<Pointer>(mem_block_aligned);
100 }
101
102 // Copy constructor to support rebind operation (to make MSVC happy).
103 template <typename U>
104 explicit AlignedAllocator<Type, Alignment>(
105 const AlignedAllocator<U, Alignment>& other) {}
106
107 // Rebind is used to allocate container internal variables of type |U|
108 // (which don't need to be aligned).
109 template <typename U>
110 struct rebind {
111 typedef AlignedAllocator<U, Alignment> other;
112 };
113};
114
115} // namespace vraudio
116
117#endif // RESONANCE_AUDIO_BASE_ALIGNED_ALLOCATOR_H_
118

source code of qtmultimedia/src/3rdparty/resonance-audio/resonance_audio/base/aligned_allocator.h