vsg  1.1.0
VulkanSceneGraph library
Allocator.h
1 #pragma once
2 
3 /* <editor-fold desc="MIT License">
4 
5 Copyright(c) 2022 Robert Osfield
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 
9 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 
13 </editor-fold> */
14 
15 #include <vsg/core/MemorySlots.h>
16 
17 #include <memory>
18 #include <mutex>
19 #include <vector>
20 
21 namespace vsg
22 {
23  enum AllocatorType : uint8_t
24  {
25  ALLOCATOR_TYPE_NO_DELETE = 0,
26  ALLOCATOR_TYPE_NEW_DELETE,
27  ALLOCATOR_TYPE_MALLOC_FREE,
28  ALLOCATOR_TYPE_VSG_ALLOCATOR
29  };
30 
31  enum AllocatorAffinity : uint32_t
32  {
33  ALLOCATOR_AFFINITY_OBJECTS,
34  ALLOCATOR_AFFINITY_DATA,
35  ALLOCATOR_AFFINITY_NODES,
36  ALLOCATOR_AFFINITY_LAST = ALLOCATOR_AFFINITY_NODES + 1
37  };
38 
40  class VSG_DECLSPEC Allocator
41  {
42  public:
43  Allocator(std::unique_ptr<Allocator> in_nestedAllocator = {});
44 
45  virtual ~Allocator();
46 
48  static std::unique_ptr<Allocator>& instance();
49 
51  virtual void* allocate(std::size_t size, AllocatorAffinity allocatorAffinity = ALLOCATOR_AFFINITY_OBJECTS);
52 
54  virtual bool deallocate(void* ptr, std::size_t size);
55 
57  virtual size_t deleteEmptyMemoryBlocks();
58 
60  virtual size_t totalAvailableSize() const;
61 
63  virtual size_t totalReservedSize() const;
64 
66  virtual size_t totalMemorySize() const;
67 
69  virtual void report(std::ostream& out) const;
70 
71  AllocatorType allocatorType = ALLOCATOR_TYPE_VSG_ALLOCATOR; // use MemoryBlocks by default
72  AllocatorType memoryBlocksAllocatorType = ALLOCATOR_TYPE_NEW_DELETE; // Use new/delete within MemoryBlocks by default
73  int memoryTracking = MEMORY_TRACKING_DEFAULT;
74 
76  void setMemoryTracking(int mt);
77 
78  struct MemoryBlock
79  {
80  MemoryBlock(size_t blockSize, int memoryTracking, AllocatorType in_allocatorType);
81  virtual ~MemoryBlock();
82 
83  void* allocate(std::size_t size);
84  bool deallocate(void* ptr, std::size_t size);
85 
86  vsg::MemorySlots memorySlots;
87  const AllocatorType allocatorType;
88  uint8_t* memory = nullptr;
89  };
90 
91  struct MemoryBlocks
92  {
93  Allocator* parent = nullptr;
94  std::string name;
95  size_t blockSize = 0;
96  std::map<void*, std::shared_ptr<MemoryBlock>> memoryBlocks;
97  std::shared_ptr<MemoryBlock> latestMemoryBlock;
98 
99  MemoryBlocks(Allocator* in_parent, const std::string& in_name, size_t in_blockSize);
100  virtual ~MemoryBlocks();
101 
102  void* allocate(std::size_t size);
103  bool deallocate(void* ptr, std::size_t size);
104 
105  size_t deleteEmptyMemoryBlocks();
106  size_t totalAvailableSize() const;
107  size_t totalReservedSize() const;
108  size_t totalMemorySize() const;
109  };
110 
111  MemoryBlocks* getMemoryBlocks(AllocatorAffinity allocatorAffinity);
112 
113  MemoryBlocks* getOrCreateMemoryBlocks(AllocatorAffinity allocatorAffinity, const std::string& name, size_t blockSize);
114 
115  void setBlockSize(AllocatorAffinity allocatorAffinity, size_t blockSize);
116 
117  mutable std::mutex mutex;
118 
119  double allocationTime = 0.0;
120  double deallocationTime = 0.0;
121 
122  protected:
123  // if you are assigning a custom allocator you must retain the old allocator to manage the memory it allocated and needs to delete
124  std::unique_ptr<Allocator> nestedAllocator;
125 
126  std::vector<std::unique_ptr<MemoryBlocks>> allocatorMemoryBlocks;
127  };
128 
130  extern VSG_DECLSPEC void* allocate(std::size_t size, AllocatorAffinity allocatorAffinity = ALLOCATOR_AFFINITY_OBJECTS);
131 
133  extern VSG_DECLSPEC void deallocate(void* ptr, std::size_t size = 0);
134 
136  template<typename T>
138  {
139  using value_type = T;
140 
141  allocator_affinity_nodes() = default;
142  template<class U>
143  explicit constexpr allocator_affinity_nodes(const allocator_affinity_nodes<U>&) noexcept {}
144 
145  value_type* allocate(std::size_t n)
146  {
147  return static_cast<value_type*>(vsg::allocate(n * sizeof(value_type), vsg::ALLOCATOR_AFFINITY_NODES));
148  }
149 
150  void deallocate(value_type* ptr, std::size_t n)
151  {
152  vsg::deallocate(ptr, n * sizeof(value_type));
153  }
154  };
155 
156  template<class T, class U>
157  bool operator==(const allocator_affinity_nodes<T>&, const allocator_affinity_nodes<U>&) { return true; }
158 
159  template<class T, class U>
160  bool operator!=(const allocator_affinity_nodes<T>&, const allocator_affinity_nodes<U>&) { return false; }
161 
162 } // namespace vsg
Definition: Allocator.h:41
void setMemoryTracking(int mt)
set the MemoryTracking member of the vsg::Allocator and all the MemoryBlocks that it manages.
virtual bool deallocate(void *ptr, std::size_t size)
deallocate, returning data to pool.
virtual size_t totalMemorySize() const
return the total memory size of allocated MemoryBlocks
virtual size_t deleteEmptyMemoryBlocks()
delete any MemoryBlock that are empty
virtual void * allocate(std::size_t size, AllocatorAffinity allocatorAffinity=ALLOCATOR_AFFINITY_OBJECTS)
allocate from the pool of memory blocks, or allocate from a new memory block
virtual void report(std::ostream &out) const
report stats about blocks of memory allocated.
virtual size_t totalAvailableSize() const
return the total available size of allocated MemoryBlocks
static std::unique_ptr< Allocator > & instance()
Allocator singleton.
virtual size_t totalReservedSize() const
return the total reserved size of allocated MemoryBlocks
Definition: MemorySlots.h:36
Definition: Allocator.h:79
Definition: Allocator.h:92
std container adapter for allocating with MEMORY_AFFINITY_NODES
Definition: Allocator.h:138