blob: f26213f954a4947dd7747db863af908fa069cf96 [file] [log] [blame]
peter klausler491122d2020-01-16 13:51:25 -08001//===-- 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
17namespace Fortran::runtime {
18
19class Terminator;
20
peter klausler95696d52020-02-04 16:55:45 -080021[[nodiscard]] void *AllocateMemoryOrCrash(
22 const Terminator &, std::size_t bytes);
Tim Keith1f879002020-03-28 21:00:16 -070023template <typename A>[[nodiscard]] A &AllocateOrCrash(const Terminator &t) {
peter klausler491122d2020-01-16 13:51:25 -080024 return *reinterpret_cast<A *>(AllocateMemoryOrCrash(t, sizeof(A)));
25}
26void FreeMemory(void *);
Tim Keith1f879002020-03-28 21:00:16 -070027template <typename A> void FreeMemory(A *p) {
peter klauslerf7be2512020-01-23 16:59:27 -080028 FreeMemory(reinterpret_cast<void *>(p));
29}
Tim Keith1f879002020-03-28 21:00:16 -070030template <typename A> void FreeMemoryAndNullify(A *&p) {
peter klauslerf7be2512020-01-23 16:59:27 -080031 FreeMemory(p);
32 p = nullptr;
33}
peter klausler491122d2020-01-16 13:51:25 -080034
Tim Keith1f879002020-03-28 21:00:16 -070035template <typename A> struct New {
36 template <typename... X>
peter klausler95696d52020-02-04 16:55:45 -080037 [[nodiscard]] A &operator()(const Terminator &terminator, X &&... x) {
peter klauslerfae12a02020-01-23 16:10:00 -080038 return *new (AllocateMemoryOrCrash(terminator, sizeof(A)))
39 A{std::forward<X>(x)...};
peter klausler491122d2020-01-16 13:51:25 -080040 }
41};
42
Tim Keith1f879002020-03-28 21:00:16 -070043template <typename A> struct OwningPtrDeleter {
peter klausler491122d2020-01-16 13:51:25 -080044 void operator()(A *p) { FreeMemory(p); }
45};
peter klausler491122d2020-01-16 13:51:25 -080046
Tim Keith1f879002020-03-28 21:00:16 -070047template <typename A> using OwningPtr = std::unique_ptr<A, OwningPtrDeleter<A>>;
peter klauslerf7be2512020-01-23 16:59:27 -080048
Tim Keith1f879002020-03-28 21:00:16 -070049template <typename A> struct Allocator {
peter klauslerf7be2512020-01-23 16:59:27 -080050 using value_type = A;
peter klausler95696d52020-02-04 16:55:45 -080051 explicit Allocator(const Terminator &t) : terminator{t} {}
Tim Keith1f879002020-03-28 21:00:16 -070052 template <typename B>
peter klauslerf7be2512020-01-23 16:59:27 -080053 explicit constexpr Allocator(const Allocator<B> &that) noexcept
Tim Keith1f879002020-03-28 21:00:16 -070054 : terminator{that.terminator} {}
peter klauslerf7be2512020-01-23 16:59:27 -080055 Allocator(const Allocator &) = default;
56 Allocator(Allocator &&) = default;
57 [[nodiscard]] constexpr A *allocate(std::size_t n) {
58 return reinterpret_cast<A *>(
59 AllocateMemoryOrCrash(terminator, n * sizeof(A)));
60 }
61 constexpr void deallocate(A *p, std::size_t) { FreeMemory(p); }
peter klausler95696d52020-02-04 16:55:45 -080062 const Terminator &terminator;
peter klauslerf7be2512020-01-23 16:59:27 -080063};
Tim Keith1f879002020-03-28 21:00:16 -070064} // namespace Fortran::runtime
peter klausler491122d2020-01-16 13:51:25 -080065
Tim Keith1f879002020-03-28 21:00:16 -070066#endif // FORTRAN_RUNTIME_MEMORY_H_