• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- runtime/memory.h ----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Thin wrapper around malloc()/free() to isolate the dependency,
10 // ease porting, and provide an owning pointer.
11 
12 #ifndef FORTRAN_RUNTIME_MEMORY_H_
13 #define FORTRAN_RUNTIME_MEMORY_H_
14 
15 #include <memory>
16 
17 namespace Fortran::runtime {
18 
19 class Terminator;
20 
21 [[nodiscard]] void *AllocateMemoryOrCrash(
22     const Terminator &, std::size_t bytes);
AllocateOrCrash(const Terminator & t)23 template <typename A> [[nodiscard]] A &AllocateOrCrash(const Terminator &t) {
24   return *reinterpret_cast<A *>(AllocateMemoryOrCrash(t, sizeof(A)));
25 }
26 void FreeMemory(void *);
FreeMemory(A * p)27 template <typename A> void FreeMemory(A *p) {
28   FreeMemory(reinterpret_cast<void *>(p));
29 }
FreeMemoryAndNullify(A * & p)30 template <typename A> void FreeMemoryAndNullify(A *&p) {
31   FreeMemory(p);
32   p = nullptr;
33 }
34 
35 template <typename A> struct OwningPtrDeleter {
operatorOwningPtrDeleter36   void operator()(A *p) { FreeMemory(p); }
37 };
38 
39 template <typename A> using OwningPtr = std::unique_ptr<A, OwningPtrDeleter<A>>;
40 
41 template <typename A> class SizedNew {
42 public:
SizedNew(const Terminator & terminator)43   explicit SizedNew(const Terminator &terminator) : terminator_{terminator} {}
44   template <typename... X>
operator()45   [[nodiscard]] OwningPtr<A> operator()(std::size_t bytes, X &&...x) {
46     return OwningPtr<A>{new (AllocateMemoryOrCrash(terminator_, bytes))
47             A{std::forward<X>(x)...}};
48   }
49 
50 private:
51   const Terminator &terminator_;
52 };
53 
54 template <typename A> struct New : public SizedNew<A> {
55   using SizedNew<A>::SizedNew;
operatorNew56   template <typename... X> [[nodiscard]] OwningPtr<A> operator()(X &&...x) {
57     return SizedNew<A>::operator()(sizeof(A), std::forward<X>(x)...);
58   }
59 };
60 
61 template <typename A> struct Allocator {
62   using value_type = A;
AllocatorAllocator63   explicit Allocator(const Terminator &t) : terminator{t} {}
64   template <typename B>
AllocatorAllocator65   explicit constexpr Allocator(const Allocator<B> &that) noexcept
66       : terminator{that.terminator} {}
67   Allocator(const Allocator &) = default;
68   Allocator(Allocator &&) = default;
allocateAllocator69   [[nodiscard]] constexpr A *allocate(std::size_t n) {
70     return reinterpret_cast<A *>(
71         AllocateMemoryOrCrash(terminator, n * sizeof(A)));
72   }
deallocateAllocator73   constexpr void deallocate(A *p, std::size_t) { FreeMemory(p); }
74   const Terminator &terminator;
75 };
76 } // namespace Fortran::runtime
77 
78 #endif // FORTRAN_RUNTIME_MEMORY_H_
79