//===-- runtime/memory.h ----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Thin wrapper around malloc()/free() to isolate the dependency, // ease porting, and provide an owning pointer. #ifndef FORTRAN_RUNTIME_MEMORY_H_ #define FORTRAN_RUNTIME_MEMORY_H_ #include namespace Fortran::runtime { class Terminator; [[nodiscard]] void *AllocateMemoryOrCrash( const Terminator &, std::size_t bytes); template [[nodiscard]] A &AllocateOrCrash(const Terminator &t) { return *reinterpret_cast(AllocateMemoryOrCrash(t, sizeof(A))); } void FreeMemory(void *); template void FreeMemory(A *p) { FreeMemory(reinterpret_cast(p)); } template void FreeMemoryAndNullify(A *&p) { FreeMemory(p); p = nullptr; } template struct OwningPtrDeleter { void operator()(A *p) { FreeMemory(p); } }; template using OwningPtr = std::unique_ptr>; template class SizedNew { public: explicit SizedNew(const Terminator &terminator) : terminator_{terminator} {} template [[nodiscard]] OwningPtr operator()(std::size_t bytes, X &&... x) { return OwningPtr{new (AllocateMemoryOrCrash(terminator_, bytes)) A{std::forward(x)...}}; } private: const Terminator &terminator_; }; template struct New : public SizedNew { using SizedNew::SizedNew; template [[nodiscard]] OwningPtr operator()(X &&... x) { return SizedNew::operator()(sizeof(A), std::forward(x)...); } }; template struct Allocator { using value_type = A; explicit Allocator(const Terminator &t) : terminator{t} {} template explicit constexpr Allocator(const Allocator &that) noexcept : terminator{that.terminator} {} Allocator(const Allocator &) = default; Allocator(Allocator &&) = default; [[nodiscard]] constexpr A *allocate(std::size_t n) { return reinterpret_cast( AllocateMemoryOrCrash(terminator, n * sizeof(A))); } constexpr void deallocate(A *p, std::size_t) { FreeMemory(p); } const Terminator &terminator; }; } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_MEMORY_H_