DART 6.13.2
Loading...
Searching...
No Matches
MemoryAllocatorDebugger-impl.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011-2022, The DART development contributors
3 * All rights reserved.
4 *
5 * The list of contributors can be found at:
6 * https://github.com/dartsim/dart/blob/master/LICENSE
7 *
8 * This file is provided under the following "BSD-style" License:
9 * Redistribution and use in source and binary forms, with or
10 * without modification, are permitted provided that the following
11 * conditions are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifndef DART_COMMON_DETAIL_MEMORYALLOCATORDEBUGGER_IMPL_HPP_
34#define DART_COMMON_DETAIL_MEMORYALLOCATORDEBUGGER_IMPL_HPP_
35
39
40namespace dart::common {
41
42//==============================================================================
43template <typename T>
44template <typename... Args>
46 : mInternalAllocator(std::forward<Args>(args)...)
47{
48 // Do nothing
49}
51//==============================================================================
52template <typename T>
54{
55 // Lock the mutex
56 std::lock_guard<std::mutex> lock(mMutex);
57
58 if (!mMapPointerToSize.empty())
59 {
60 size_t totalSize = 0;
61 for (auto it : mMapPointerToSize)
62 {
63 void* pointer = it.first;
64 size_t size = it.second;
65 totalSize += size;
66 dtdbg << "Found potential memory leak at " << pointer << " (" << size
67 << " bytes).\n";
68 // TODO(JS): Change to DART_FATAL once the issue of calling spdlog in
69 // destructor is resolved.
70 }
72 dtdbg << "Found potential memory leak of total " << totalSize
73 << " bytes. The internal allocator will try to forcefully "
74 << "deallocate it but it's is not guaranteed.\n";
75 // TODO(JS): Change to DART_FATAL once the issue of calling spdlog in
76 // destructor is resolved.
77 }
78}
79
80//==============================================================================
81template <typename T>
83{
84 static const std::string type
85 = "MemoryAllocatorDebugger<" + T::getStaticType() + ">";
86 return type;
87}
88
89//==============================================================================
90template <typename T>
91const std::string& MemoryAllocatorDebugger<T>::getType() const
92{
93 return getStaticType();
94}
95
96//==============================================================================
97template <typename T>
98void* MemoryAllocatorDebugger<T>::allocate(size_t bytes) noexcept
99{
100 void* newPtr = mInternalAllocator.allocate(bytes);
101
102 if (newPtr)
103 {
104 std::lock_guard<std::mutex> lock(mMutex);
105 mSize += bytes;
106 mPeak = std::max(mPeak, mSize);
107 mMapPointerToSize[newPtr] = bytes;
108 }
109
110 return newPtr;
111}
112
113//==============================================================================
114template <typename T>
115void MemoryAllocatorDebugger<T>::deallocate(void* pointer, size_t bytes)
116{
117 std::lock_guard<std::mutex> lock(mMutex);
118
119 auto it = mMapPointerToSize.find(pointer);
120 if (it == mMapPointerToSize.end())
121 {
123 "Cannot deallocate memory {} not allocated by this allocator.",
124 pointer);
125 return;
126 }
127
128 auto allocatedSize = it->second;
129 if (bytes != allocatedSize)
130 {
132 "Cannot deallocate memory at {} of {} bytes that is different from the "
133 "allocated size {}, which is a critical bug.",
134 pointer,
135 bytes,
136 allocatedSize);
137 return;
138 }
139
140 mInternalAllocator.deallocate(pointer, bytes);
141 mMapPointerToSize.erase(it);
142 mSize -= bytes;
143}
144
145//==============================================================================
146template <typename T>
148{
149 std::lock_guard<std::mutex> lock(mMutex);
150 return mMapPointerToSize.empty();
151}
152
153//==============================================================================
154template <typename T>
155bool MemoryAllocatorDebugger<T>::hasAllocated(void* pointer, size_t size) const
156{
157 std::lock_guard<std::mutex> lock(mMutex);
158
159 const auto it = mMapPointerToSize.find(pointer);
160 if (it == mMapPointerToSize.end())
161 {
162 return false;
163 }
164
165 const auto& allocatedSize = it->second;
166 if (size != allocatedSize)
167 {
168 return false;
169 }
170
171 return true;
172}
173
174//==============================================================================
175template <typename T>
177{
178 return mInternalAllocator;
179}
180
181//==============================================================================
182template <typename T>
184{
185 return mInternalAllocator;
186}
187
188//==============================================================================
189template <typename T>
190void MemoryAllocatorDebugger<T>::print(std::ostream& os, int indent) const
191{
192 if (indent == 0)
193 {
194 os << "[" << getType() << "]\n";
195 }
196 const std::string spaces(indent, ' ');
197 if (indent != 0)
198 {
199 os << spaces << "type: " << getType() << "\n";
200 }
201 std::lock_guard<std::mutex> lock(mMutex);
202 os << spaces << "size_in_bytes: " << mSize << "\n";
203 os << spaces << "peak: " << mPeak << "\n";
204 os << spaces << "internal_allocator:\n";
205 mInternalAllocator.print(os, indent + 2);
206}
207
208} // namespace dart::common
209
210#endif // DART_COMMON_DETAIL_MEMORYALLOCATORDEBUGGER_IMPL_HPP_
#define dtdbg
Output a debug message.
Definition Console.hpp:43
#define DART_DEBUG(...)
Definition Logging.hpp:60
std::string type
Definition SdfParser.cpp:82
void * allocate(size_t bytes) noexcept override
Allocates size bytes of uninitialized storage.
Definition MemoryAllocatorDebugger-impl.hpp:98
bool hasAllocated(void *pointer, size_t size) const
Returns true if a pointer is allocated by the internal allocator.
Definition MemoryAllocatorDebugger-impl.hpp:155
void deallocate(void *pointer, size_t bytes) override
Deallocates the storage referenced by the pointer p, which must be a pointer obtained by an earlier c...
Definition MemoryAllocatorDebugger-impl.hpp:115
const std::string & getType() const override
Returns type string.
Definition MemoryAllocatorDebugger-impl.hpp:91
MemoryAllocatorDebugger(Args &&... args)
Constructor.
Definition MemoryAllocatorDebugger-impl.hpp:45
bool isEmpty() const
Returns true if there is no memory allocated by the internal allocator.
Definition MemoryAllocatorDebugger-impl.hpp:147
const T & getInternalAllocator() const
Returns the internal allocator.
Definition MemoryAllocatorDebugger-impl.hpp:176
~MemoryAllocatorDebugger()
Destructor.
Definition MemoryAllocatorDebugger-impl.hpp:53
static const std::string & getStaticType()
Returns type string.
Definition MemoryAllocatorDebugger-impl.hpp:82
void print(std::ostream &os=std::cout, int indent=0) const override
Prints state of the memory allocator.
Definition MemoryAllocatorDebugger-impl.hpp:190
Definition Aspect.cpp:42