-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
aligned_memory.h
101 lines (83 loc) · 3.99 KB
/
aligned_memory.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright 2010-2024 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Provides functions and data structures that make it easier to work with
// aligned memory:
//
// - AlignedAllocator<T, n>, an extension of std::allocator<T> that also takes
// an explicit memory alignment parameter. The memory blocks returned by the
// allocator are aligned to this number of bytes, i.e. the address of the
// beginning of the block will be N * alignment_bytes for some N.
// - AlignedVector<>, a specialization of std::vector<> that uses the aligned
// allocator to create blocks with explicit allocations.
//
// - AlignUp and AlignDown are functions that align a pointer to the given
// number of bytes.
#ifndef OR_TOOLS_UTIL_ALIGNED_MEMORY_H_
#define OR_TOOLS_UTIL_ALIGNED_MEMORY_H_
#include <cstddef>
#include <cstdint>
#include <vector>
#include "ortools/util/aligned_memory_internal.h"
namespace operations_research {
// Functions for working with pointers and rounding them up and down to a given
// alignment.
// Returns the nearest greater or equal address that is a multiple of
// alignment_bytes. When ptr is already aligned to alignment_bytes, returns it
// unchanged.
template <size_t alignment_bytes, typename Value>
inline Value* AlignUp(Value* ptr) {
const std::uintptr_t int_ptr = reinterpret_cast<std::intptr_t>(ptr);
const std::uintptr_t misalignment = int_ptr % alignment_bytes;
if (misalignment == 0) return ptr;
return reinterpret_cast<Value*>(int_ptr - misalignment + alignment_bytes);
}
// Returns the nearest smaller or equal address that is a multiple of
// alignment_bytes. When ptr is already aligned to alignment_bytes, returns it
// unchanged
template <size_t alignment_bytes, typename Value>
inline Value* AlignDown(Value* ptr) {
const std::intptr_t int_ptr = reinterpret_cast<std::intptr_t>(ptr);
const std::intptr_t misalignment = int_ptr % alignment_bytes;
return reinterpret_cast<Value*>(int_ptr - misalignment);
}
// Returns true when `ptr` is aligned to `alignment_bytes` bytes.
template <size_t alignment_bytes, typename Value>
inline bool IsAligned(Value* ptr) {
return reinterpret_cast<std::uintptr_t>(ptr) % alignment_bytes == 0;
}
// Support for aligned containers in STL.
// An allocator that always aligns its memory to `alignment_bytes`.
template <typename T, size_t alignment_bytes>
using AlignedAllocator =
internal::AllocatorWithAlignment<T, alignment_bytes, 0>;
// A version of std::vector<T> whose data() pointer is always aligned to
// `alignment_bytes`.
template <typename T, size_t alignment_bytes>
using AlignedVector = std::vector<T, AlignedAllocator<T, alignment_bytes>>;
// Intentionally misaligned containers for testing correctness and performance
// of code that may depend on a certain alignment.
namespace use_only_in_tests {
// A version of AlignedAllocator for testing purposes that adds intentional
// misalignment. The returned address has the form
// alignment_bytes * N + misalignment_bytes.
template <typename T, size_t alignment_bytes, size_t misalignment_bytes>
using MisalignedAllocator =
internal::AllocatorWithAlignment<T, alignment_bytes, misalignment_bytes>;
// A specialization of std::vector<> that uses MisalignedAllocator with the
// given parameters.
template <typename T, size_t alignment_bytes, size_t misalignment_bytes>
using MisalignedVector =
std::vector<T, MisalignedAllocator<T, alignment_bytes, misalignment_bytes>>;
} // namespace use_only_in_tests
} // namespace operations_research
#endif // OR_TOOLS_UTIL_ALIGNED_MEMORY_H_