Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
aligned_memory_internal.h
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_UTIL_ALIGNED_MEMORY_INTERNAL_H_
15#define OR_TOOLS_UTIL_ALIGNED_MEMORY_INTERNAL_H_
16
17#include <cstddef>
18#include <cstdint>
19#include <cstdlib>
20#include <memory>
21
23
24namespace operations_research {
25
26namespace internal {
27
28template <typename T, size_t alignment_bytes, size_t misalignment_bytes>
29struct AllocatorWithAlignment : public std::allocator<T> {
30 // Allocates memory for num_items items of type T. The memory must be freed
31 // using deallocate(); using it with free() or `delete` might cause unexpected
32 // behavior when misalignment is used.
33 T* allocate(size_t num_items) {
34 // Having misalignment_bytes >= alignment_bytes is useless, because all
35 // misalignments are equivalent modulo `alignment_bytes`. Disallowing it
36 // allows us to simplify the code below.
37 static_assert(alignment_bytes == 0 || misalignment_bytes < alignment_bytes);
38
39 // `std::aligned_alloc(alignment, size)` requires that `size` is a multiple
40 // of `alignment`, and might return a nullptr when this is not respected. To
41 // be safe, we round the number of bytes up to alignment.
42 const size_t num_required_bytes =
43 misalignment_bytes + num_items * sizeof(T);
44
45 const size_t num_allocated_bytes =
46 MathUtil::RoundUpTo(num_required_bytes, alignment_bytes);
47
48 std::uintptr_t ptr = reinterpret_cast<std::uintptr_t>(
49#if !defined(_MSC_VER)
50 std::aligned_alloc(alignment_bytes, num_allocated_bytes));
51#else
52 _aligned_malloc(alignment_bytes, num_allocated_bytes));
53#endif
54 return reinterpret_cast<T*>(ptr + misalignment_bytes);
55 }
56 // A version of allocate() that takes a hint; we just ignore the hint.
57 T* allocate(size_t n, const void*) { return allocate(n); }
58
59 // Frees memory allocated by allocate().
60 void deallocate(T* p, size_t) {
61 std::uintptr_t aligned_pointer =
62 reinterpret_cast<std::uintptr_t>(p) - misalignment_bytes;
63 free(reinterpret_cast<void*>(aligned_pointer));
64 }
65
66 // Rebind must be specialized to produce AllocatorWithAlignment and not
67 // std::allocator. It uses the same alignment and misalignment as its source.
68 template <typename U>
73};
74
75} // namespace internal
76
77} // namespace operations_research
78
79#endif // OR_TOOLS_UTIL_ALIGNED_MEMORY_INTERNAL_H_
static IntType RoundUpTo(IntType input_value, IntType rounding_value)
Definition mathutil.h:144
In SWIG mode, we don't want anything besides these top-level includes.
void free(void *)
T * allocate(size_t n, const void *)
A version of allocate() that takes a hint; we just ignore the hint.
void deallocate(T *p, size_t)
Frees memory allocated by allocate().