blob: 4b09fe80772ed85b4b00a0d388e0c1782d6634d7 [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 Keithdd904082020-07-01 16:51:44 -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 OwningPtrDeleter {
peter klausler491122d2020-01-16 13:51:25 -080036 void operator()(A *p) { FreeMemory(p); }
37};
peter klausler491122d2020-01-16 13:51:25 -080038
Tim Keith1f879002020-03-28 21:00:16 -070039template <typename A> using OwningPtr = std::unique_ptr<A, OwningPtrDeleter<A>>;
peter klauslerf7be2512020-01-23 16:59:27 -080040
peter klausler98d576c2020-07-02 18:35:20 -070041template <typename A> class SizedNew {
42public:
43 explicit SizedNew(const Terminator &terminator) : terminator_{terminator} {}
44 template <typename... X>
peter klausler675ad1b2020-08-03 11:35:29 -070045 [[nodiscard]] OwningPtr<A> operator()(std::size_t bytes, X &&...x) {
peter klausler98d576c2020-07-02 18:35:20 -070046 return OwningPtr<A>{new (AllocateMemoryOrCrash(terminator_, bytes))
47 A{std::forward<X>(x)...}};
48 }
49
50private:
51 const Terminator &terminator_;
52};
53
54template <typename A> struct New : public SizedNew<A> {
55 using SizedNew<A>::SizedNew;
peter klausler675ad1b2020-08-03 11:35:29 -070056 template <typename... X> [[nodiscard]] OwningPtr<A> operator()(X &&...x) {
peter klausler98d576c2020-07-02 18:35:20 -070057 return SizedNew<A>::operator()(sizeof(A), std::forward<X>(x)...);
58 }
59};
60
Tim Keith1f879002020-03-28 21:00:16 -070061template <typename A> struct Allocator {
peter klauslerf7be2512020-01-23 16:59:27 -080062 using value_type = A;
peter klausler95696d52020-02-04 16:55:45 -080063 explicit Allocator(const Terminator &t) : terminator{t} {}
Tim Keith1f879002020-03-28 21:00:16 -070064 template <typename B>
peter klauslerf7be2512020-01-23 16:59:27 -080065 explicit constexpr Allocator(const Allocator<B> &that) noexcept
Tim Keith1f879002020-03-28 21:00:16 -070066 : terminator{that.terminator} {}
peter klauslerf7be2512020-01-23 16:59:27 -080067 Allocator(const Allocator &) = default;
68 Allocator(Allocator &&) = default;
69 [[nodiscard]] constexpr A *allocate(std::size_t n) {
70 return reinterpret_cast<A *>(
71 AllocateMemoryOrCrash(terminator, n * sizeof(A)));
72 }
73 constexpr void deallocate(A *p, std::size_t) { FreeMemory(p); }
peter klausler95696d52020-02-04 16:55:45 -080074 const Terminator &terminator;
peter klauslerf7be2512020-01-23 16:59:27 -080075};
Tim Keith1f879002020-03-28 21:00:16 -070076} // namespace Fortran::runtime
peter klausler491122d2020-01-16 13:51:25 -080077
Tim Keith1f879002020-03-28 21:00:16 -070078#endif // FORTRAN_RUNTIME_MEMORY_H_