Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
MemoryAllocator.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Memory_MemoryAllocator_h_
5#define _Stroika_Foundation_Memory_MemoryAllocator_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <atomic>
10#include <map>
11#include <memory>
12#include <mutex>
13
14#include "Stroika/Foundation/Memory/Common.h"
15
16/**
17 * \file
18 *
19 */
20
21namespace Stroika::Foundation::Memory {
22
23 /**
24 * This defines a generic abstract 'Allocator' API - for allocating (and freeing) memory.
25 * This is far simpler than than the STL/stdC++ allocator policy (for example, not templated, and uses C model
26 * of memory - just a byte pointer and amount).
27 *
28 * @todo Consider if we should have a notion of alignment, or if any of the other stdc++ allocator stuff is
29 * needed here...
30 */
32 protected:
33 virtual ~AbstractGeneralPurposeAllocator () = default;
34
35 // Allocate never returns nullptr and Deallocate () should not be called with nullptr
36 // Allocate throws bad_alloc () on failure to allocate
37 public:
38 virtual void* Allocate (size_t size) = 0;
39 virtual void Deallocate (void* p) = 0;
40 };
41
42 /**
43 * SimpleAllocator_CallLIBCMallocFree implements the AbstractGeneralPurposeAllocator just using malloc and free.
44 */
46 public:
47 virtual void* Allocate (size_t size) override;
48 virtual void Deallocate (void* p) override;
49 };
50
51 /**
52 * SimpleAllocator_CallLIBCNewDelete implements the AbstractGeneralPurposeAllocator just using stdC++ new/delete.
53 */
55 public:
56 virtual void* Allocate (size_t size) override;
57 virtual void Deallocate (void* p) override;
58 };
59
60 /**
61 * The STLAllocator takes a Stroika Allocator class (as template argument) and maps it
62 * for usage as an STL-style allocator.
63 *
64 * @todo unsure about how to handle propagate_on_container_copy_assignment, etc. For all my current allocators, this
65 * is fine (false), but if they had data, obviously it would be different. Perhaps that choice should be
66 * parametized (as it is with normal C++ allocators). Or maybe leave subclassing this STLAllocator<> as a way
67 * todo that? Thats probably good enuf...
68 *
69 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
70 * o only operator== is defined, and is boring
71 * @see https://en.cppreference.com/w/cpp/memory/allocator/operator_cmp
72 */
73 template <typename T, typename BASE_ALLOCATOR = SimpleAllocator_CallLIBCMallocFree>
75 public:
77 using value_type = T;
78 using pointer = value_type*;
79 using const_pointer = const value_type*;
80 using void_pointer = void*;
81 using const_void_pointer = const void*;
82 using reference = value_type&;
83 using const_reference = const value_type&;
84 using size_type = size_t;
85 using difference_type = ptrdiff_t;
86 using propagate_on_container_copy_assignment = false_type;
87 using propagate_on_container_move_assignment = false_type;
88 using propagate_on_container_swap = false_type;
89
90 public:
91 template <typename OTHER>
92 struct rebind {
94 };
95
96 public:
97 BASE_ALLOCATOR fBaseAllocator;
98
99 public:
100 explicit STLAllocator ();
102 template <typename OTHER>
104 template <typename OTHER>
106
107 public:
108 nonvirtual STLAllocator<T, BASE_ALLOCATOR> select_on_container_copy_construction () const;
109
110 public:
111 nonvirtual pointer address (reference v) const noexcept;
112 nonvirtual const_pointer address (const_reference v) const noexcept;
113
114 public:
115 nonvirtual pointer allocate (size_type nElements);
116 nonvirtual pointer allocate (size_type nElements, const void* ptr);
117 nonvirtual void deallocate (pointer ptr, size_type sz);
118
119 public:
120 nonvirtual void construct (pointer p);
121 nonvirtual void construct (pointer p, const T& v);
122
123 public:
124 template <typename OTHERT>
125 nonvirtual void destroy (OTHERT* p);
126
127 public:
128 template <typename... ARGS>
129 nonvirtual void construct (pointer p, ARGS&&... args);
130
131 public:
132 nonvirtual size_t max_size () const noexcept;
133
134 public:
135 nonvirtual bool operator== (const STLAllocator& rhs) const;
136 };
137
138 /**
139 * The SimpleSizeCountingGeneralPurposeAllocator is a Stroika-style AbstractGeneralPurposeAllocator which keeps statistics, and delegates to
140 * some real allocator (constructor argument).
141 */
143 public:
147
148 public:
149 virtual void* Allocate (size_t size) override;
150 virtual void Deallocate (void* p) override;
151
152 public:
153 nonvirtual size_t GetNetAllocationCount () const;
154 nonvirtual size_t GetNetAllocatedByteCount () const;
155
156 private:
157 AbstractGeneralPurposeAllocator& fBaseAllocator_;
158 atomic<uint32_t> fNetAllocationCount_{0};
159 atomic<size_t> fNetAllocatedByteCount_{0};
160 };
161
162 /**
163 * The LeakTrackingGeneralPurposeAllocator is a Stroika-style AbstractGeneralPurposeAllocator which
164 * keeps LOTS of statistics - it tracks all allocations, and delegates to some real allocator
165 * (constructor argument).
166 */
168 public:
169 using PTRMAP = map<void*, size_t, less<void*>>;
170
171 public:
172 /**
173 *
174 */
177
178 public:
180
181 public:
182 virtual void* Allocate (size_t size) override;
183 virtual void Deallocate (void* p) override;
184
185 public:
186 nonvirtual size_t GetNetAllocationCount () const;
187 nonvirtual size_t GetNetAllocatedByteCount () const;
188
189 public:
190 /**
191 *
192 */
193 class Snapshot {
194 public:
195 Snapshot () = default;
196 explicit Snapshot (const PTRMAP& m);
197
198 public:
199 PTRMAP fAllocations;
200 };
201
202 public:
203 nonvirtual Snapshot GetSnapshot () const;
204 nonvirtual void DUMPCurMemStats (const Snapshot& sinceSnapshot = Snapshot{});
205
206 private:
207 mutable recursive_mutex fCritSection_;
208 AbstractGeneralPurposeAllocator& fBaseAllocator_;
209 PTRMAP fAllocations_;
210 };
211
212}
213
214/*
215 ********************************************************************************
216 ***************************** Implementation Details ***************************
217 ********************************************************************************
218 */
219#include "MemoryAllocator.inl"
220
221#endif /*_Stroika_Foundation_Memory_MemoryAllocator_h_*/