aboutsummaryrefslogtreecommitdiff
path: root/pw_allocator/public/pw_allocator/freelist_heap.h
blob: 673302627707e63a861a43215179ca9d9b443477 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright 2020 The Pigweed Authors
//
// 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
//
//     https://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.

#pragma once

#include <cstddef>

#include "pw_allocator/block.h"
#include "pw_allocator/freelist.h"
#include "pw_span/span.h"

namespace pw::allocator {

class FreeListHeap {
 public:
  template <size_t kNumBuckets>
  friend class FreeListHeapBuffer;
  struct HeapStats {
    size_t total_bytes;
    size_t bytes_allocated;
    size_t cumulative_allocated;
    size_t cumulative_freed;
    size_t total_allocate_calls;
    size_t total_free_calls;
  };
  FreeListHeap(span<std::byte> region, FreeList& freelist);

  void* Allocate(size_t size);
  void Free(void* ptr);
  void* Realloc(void* ptr, size_t size);
  void* Calloc(size_t num, size_t size);

  void LogHeapStats();

 private:
  span<std::byte> BlockToSpan(Block* block) {
    return span<std::byte>(block->UsableSpace(), block->InnerSize());
  }

  void InvalidFreeCrash();

  span<std::byte> region_;
  FreeList& freelist_;
  HeapStats heap_stats_;
};

template <size_t kNumBuckets = 6>
class FreeListHeapBuffer {
 public:
  static constexpr std::array<size_t, kNumBuckets> defaultBuckets{
      16, 32, 64, 128, 256, 512};

  FreeListHeapBuffer(span<std::byte> region)
      : freelist_(defaultBuckets), heap_(region, freelist_) {}

  void* Allocate(size_t size) { return heap_.Allocate(size); }
  void Free(void* ptr) { heap_.Free(ptr); }
  void* Realloc(void* ptr, size_t size) { return heap_.Realloc(ptr, size); }
  void* Calloc(size_t num, size_t size) { return heap_.Calloc(num, size); }

  const FreeListHeap::HeapStats& heap_stats() const {
    return heap_.heap_stats_;
  }

  void LogHeapStats() { heap_.LogHeapStats(); }

 private:
  FreeListBuffer<kNumBuckets> freelist_;
  FreeListHeap heap_;
};

}  // namespace pw::allocator