// Copyright 2010-2025 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, an extension of std::allocator 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 ORTOOLS_UTIL_ALIGNED_MEMORY_H_ #define ORTOOLS_UTIL_ALIGNED_MEMORY_H_ #include #include #include #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 inline Value* AlignUp(Value* ptr) { const std::uintptr_t int_ptr = reinterpret_cast(ptr); const std::uintptr_t misalignment = int_ptr % alignment_bytes; if (misalignment == 0) return ptr; return reinterpret_cast(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 inline Value* AlignDown(Value* ptr) { const std::intptr_t int_ptr = reinterpret_cast(ptr); const std::intptr_t misalignment = int_ptr % alignment_bytes; return reinterpret_cast(int_ptr - misalignment); } // Returns true when `ptr` is aligned to `alignment_bytes` bytes. template inline bool IsAligned(Value* ptr) { return reinterpret_cast(ptr) % alignment_bytes == 0; } // Support for aligned containers in STL. // An allocator that always aligns its memory to `alignment_bytes`. template using AlignedAllocator = internal::AllocatorWithAlignment; // A version of std::vector whose data() pointer is always aligned to // `alignment_bytes`. template using AlignedVector = std::vector>; // 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 using MisalignedAllocator = internal::AllocatorWithAlignment; // A specialization of std::vector<> that uses MisalignedAllocator with the // given parameters. template using MisalignedVector = std::vector>; } // namespace use_only_in_tests } // namespace operations_research #endif // ORTOOLS_UTIL_ALIGNED_MEMORY_H_