27 #include <unordered_map> 36 static constexpr
size_t Log2(
size_t x) {
return x <= 1 ? 0 : (
Log2(x/2) + 1); }
56 PtrInfo(
const void * _ptr,
size_t _array_bytes)
57 : ptr(_ptr), count(1), status(
PtrStatus::ARRAY), array_bytes(_array_bytes)
61 std::cout <<
"Created info for array pointer (bytes=" << array_bytes <<
"): " 75 const void *
GetPtr() const noexcept {
return ptr; }
78 int GetCount() const noexcept {
return count; }
84 bool IsActive() const noexcept {
return (
bool) status; }
115 bool OK() const noexcept {
116 if (ptr ==
nullptr)
return false;
118 if (array_bytes == 0)
return false;
119 if (count == 0)
return false;
122 if (array_bytes > 0)
return false;
123 if (count == 0)
return false;
133 std::unordered_map<const void *, size_t> ptr_id;
135 static constexpr
size_t UNTRACKED_ID = (size_t) -1;
139 std::cout <<
"EMP_TRACK_MEM: Pointer tracking is active!\n";
153 for (
const auto & info : id_info) {
155 if (info.GetCount()) remain++;
157 emp_assert(info.IsActive() ==
false, info.GetPtr(), info.GetCount(), info.IsActive());
160 std::cout <<
"EMP_TRACK_MEM: No memory leaks found!\n " 161 << total <<
" pointers found; " 162 << remain <<
" still exist with a non-null value (but have been properly deleted)" 176 return ptr_id.find(ptr) != ptr_id.end();
186 size_t GetArrayBytes(
size_t id)
const {
return id_info[id].GetArrayBytes(); }
190 if (
id == UNTRACKED_ID)
return false;
192 return !id_info[id].IsActive();
198 if (ptr_id.find(ptr) == ptr_id.end())
return false;
199 return GetInfo(ptr).IsActive();
204 if (
id == UNTRACKED_ID)
return false;
205 if (
id >= id_info.
size())
return false;
206 return id_info[id].IsActive();
212 return id_info[id].IsArray();
218 return id_info[id].GetCount();
222 size_t New(
const void * ptr) {
224 size_t id = id_info.
size();
225 #ifdef EMP_ABORT_PTR_NEW 226 if (
id == EMP_ABORT_PTR_NEW) {
227 std::cerr <<
"Aborting at creation of Ptr id " <<
id <<
std::endl;
233 emp_assert(!HasPtr(ptr) || IsDeleted(GetCurID(ptr)),
id);
240 size_t NewArray(
const void * ptr,
size_t array_bytes) {
241 size_t id = New(ptr);
243 id_info[id].SetArray(array_bytes);
249 if (
id == UNTRACKED_ID)
return;
256 if (
id == UNTRACKED_ID)
return;
257 auto & info = id_info[id];
259 emp_assert(info.GetCount() > 0,
"Decrementing Ptr, but already zero!",
260 id, info.GetPtr(), info.IsActive());
266 #ifdef EMP_ABORT_PTR_DELETE 267 if (
id == EMP_ABORT_PTR_DELETE) {
268 std::cerr <<
"Aborting at deletion of Ptr id " <<
id <<
std::endl;
273 emp_assert(id_info[
id].IsActive(),
"Deleting same emp::Ptr a second time!",
id);
274 id_info[id].MarkDeleted();
289 template <
typename FROM,
typename TO>
290 bool PtrIsConvertable(FROM * ptr) {
return true; }
297 PtrDebug() : current(0), total(0) { ; }
298 void AddPtr() { current++; total++; }
299 void RemovePtr() { current--; }
303 template <
typename TYPE>
308 using element_type = TYPE;
310 static constexpr
size_t UNTRACKED_ID = (size_t) -1;
312 static PtrDebug & DebugInfo() {
static PtrDebug info;
return info; }
316 Ptr() : ptr(
nullptr), id(UNTRACKED_ID) {
330 _in.id = UNTRACKED_ID;
335 template <
typename T2>
336 Ptr(T2 * in_ptr,
bool track=
false) : ptr(in_ptr), id(UNTRACKED_ID)
339 emp_assert( (PtrIsConvertable<T2, TYPE>(in_ptr)) );
342 if (Tracker().IsActive(ptr)) {
343 id = Tracker().GetCurID(ptr);
348 id = Tracker().New(ptr);
349 DebugInfo().AddPtr();
354 template <
typename T2>
355 Ptr(T2 * _ptr,
size_t array_size,
bool track) : ptr(_ptr), id(UNTRACKED_ID)
357 const size_t array_bytes = array_size *
sizeof(T2);
359 <<
". size=" << array_size <<
"(" << array_bytes
360 <<
" bytes); track=" << track <<
std::endl;
361 emp_assert( (PtrIsConvertable<T2, TYPE>(_ptr)) );
364 if (Tracker().IsActive(ptr)) {
365 id = Tracker().GetCurID(ptr);
367 emp_assert(Tracker().GetArrayBytes(
id) == array_bytes);
371 id = Tracker().NewArray(ptr, array_bytes);
372 DebugInfo().AddPtr();
377 template <
typename T2>
385 Ptr(std::nullptr_t) :
Ptr() {
392 std::cout <<
"destructing Ptr instance ";
393 if (ptr) std::cout <<
id <<
" (" << ptr <<
")\n";
394 else std::cout <<
"(nullptr)\n";
400 bool IsNull()
const {
return ptr ==
nullptr; }
404 emp_assert(Tracker().IsDeleted(
id) ==
false,
"Do not convert deleted Ptr to raw.",
id);
409 const TYPE *
const Raw()
const {
410 emp_assert(Tracker().IsDeleted(
id) ==
false,
"Do not convert deleted Ptr to raw.",
id);
415 template <
typename T2>
Ptr<T2> Cast() {
416 emp_assert(Tracker().IsDeleted(
id) ==
false,
"Do not cast deleted pointers.",
id);
422 emp_assert(Tracker().IsDeleted(
id) ==
false,
"Do not cast deleted pointers.",
id);
427 template <
typename T2>
Ptr<T2> DynamicCast() {
428 emp_assert(dynamic_cast<T2*>(ptr) !=
nullptr);
429 emp_assert(Tracker().IsDeleted(
id) ==
false,
"Do not cast deleted pointers.",
id);
434 size_t GetID()
const {
return id; }
437 template <
typename... T>
438 void New(T &&... args) {
441 ptr =
new TYPE(std::forward<T>(args)...);
447 id = Tracker().New(ptr);
448 DebugInfo().AddPtr();
452 template <
typename... T>
453 void NewArray(
size_t array_size, T &&... args) {
460 ptr =
new TYPE[array_size];
468 id = Tracker().NewArray(ptr, array_size *
sizeof(TYPE));
469 DebugInfo().AddPtr();
474 emp_assert(
id < Tracker().GetNumIDs(),
id,
"Deleting Ptr that we are not resposible for.");
476 emp_assert(Tracker().IsArrayID(
id) ==
false,
id,
"Trying to delete array pointer as non-array.");
479 Tracker().MarkDeleted(
id);
480 DebugInfo().RemovePtr();
485 emp_assert(
id < Tracker().GetNumIDs(),
id,
"Deleting Ptr that we are not resposible for.");
487 emp_assert(Tracker().IsArrayID(
id),
id,
"Trying to delete non-array pointer as array.");
490 Tracker().MarkDeleted(
id);
491 DebugInfo().RemovePtr();
495 size_t Hash()
const {
498 return (
size_t)(ptr) >> shift;
500 struct hash_t {
size_t operator()(
const Ptr<TYPE> & t)
const {
return t.
Hash(); } };
505 emp_assert(Tracker().IsDeleted(_in.id) ==
false, _in.id,
"Do not copy deleted pointers.");
518 emp_assert(Tracker().IsDeleted(_in.id) ==
false, _in.id,
"Do not move deleted pointers.");
519 if (ptr != _in.ptr) {
524 _in.id = UNTRACKED_ID;
531 template <
typename T2>
534 emp_assert( (PtrIsConvertable<T2, TYPE>(_in)) );
540 if (Tracker().IsActive(ptr)) {
541 id = Tracker().GetCurID(ptr);
553 template <
typename T2>
556 emp_assert( (PtrIsConvertable<T2, TYPE>(_in.
Raw())), _in.id );
557 emp_assert(Tracker().IsDeleted(_in.id) ==
false, _in.id,
"Do not copy deleted pointers.");
568 emp_assert(Tracker().IsDeleted(
id) ==
false ,
id);
569 emp_assert(ptr !=
nullptr,
"Do not dereference a null pointer!");
574 const TYPE & operator*()
const {
576 emp_assert(Tracker().IsDeleted(
id) ==
false ,
id);
577 emp_assert(ptr !=
nullptr,
"Do not dereference a null pointer!");
582 TYPE * operator->() {
584 emp_assert(Tracker().IsDeleted(
id) ==
false ,
id);
585 emp_assert(ptr !=
nullptr,
"Do not follow a null pointer!");
590 TYPE *
const operator->()
const {
592 emp_assert(Tracker().IsDeleted(
id) ==
false ,
id);
593 emp_assert(ptr !=
nullptr,
"Do not follow a null pointer!");
598 TYPE & operator[](
size_t pos) {
599 emp_assert(Tracker().IsDeleted(
id) ==
false ,
id);
600 emp_assert(Tracker().IsArrayID(
id),
"Only arrays can be indexed into.",
id);
601 emp_assert(Tracker().GetArrayBytes(
id) > (pos*
sizeof(TYPE)),
602 "Indexing out of range.",
id, ptr, pos,
sizeof(TYPE), Tracker().GetArrayBytes(
id));
603 emp_assert(ptr !=
nullptr,
"Do not follow a null pointer!");
608 const TYPE & operator[](
size_t pos)
const {
609 emp_assert(Tracker().IsDeleted(
id) ==
false ,
id);
610 emp_assert(Tracker().IsArrayID(
id),
"Only arrays can be indexed into.",
id);
611 emp_assert(Tracker().GetArrayBytes(
id) > (pos*
sizeof(TYPE)),
612 "Indexing out of range.",
id, ptr, pos,
sizeof(TYPE), Tracker().GetArrayBytes(
id));
613 emp_assert(ptr !=
nullptr,
"Do not follow a null pointer!");
620 emp_assert(Tracker().IsDeleted(
id) ==
false ,
id);
628 operator bool() {
return ptr !=
nullptr; }
631 operator bool()
const {
return ptr !=
nullptr; }
634 bool operator==(
const Ptr<TYPE> & in_ptr)
const {
return ptr == in_ptr.ptr; }
637 bool operator!=(
const Ptr<TYPE> & in_ptr)
const {
return ptr != in_ptr.ptr; }
640 bool operator<(const Ptr<TYPE> & in_ptr)
const {
return ptr < in_ptr.ptr; }
643 bool operator<=(const Ptr<TYPE> & in_ptr)
const {
return ptr <= in_ptr.ptr; }
646 bool operator>(
const Ptr<TYPE> & in_ptr)
const {
return ptr > in_ptr.ptr; }
649 bool operator>=(
const Ptr<TYPE> & in_ptr)
const {
return ptr >= in_ptr.ptr; }
653 bool operator==(
const TYPE * in_ptr)
const {
return ptr == in_ptr; }
656 bool operator!=(
const TYPE * in_ptr)
const {
return ptr != in_ptr; }
659 bool operator<(
const TYPE * in_ptr)
const {
return ptr < in_ptr; }
662 bool operator<=(
const TYPE * in_ptr)
const {
return ptr <= in_ptr; }
665 bool operator>(
const TYPE * in_ptr)
const {
return ptr > in_ptr; }
668 bool operator>=(
const TYPE * in_ptr)
const {
return ptr >= in_ptr; }
672 int DebugGetCount()
const {
return Tracker().GetIDCount(
id); }
673 bool DebugIsArray()
const {
return Tracker().IsArrayID(
id); }
674 size_t DebugGetArrayBytes()
const {
return Tracker().GetArrayBytes(
id); }
675 bool DebugIsActive()
const {
return Tracker().IsActiveID(
id); }
679 if (
id == UNTRACKED_ID)
return !Tracker().HasPtr(ptr);
682 if (Tracker().GetInfo(
id).GetPtr() != ptr)
return false;
685 return Tracker().GetInfo(
id).OK();
710 template <
typename TYPE>
721 template <
typename T2>
Ptr(T2 * in_ptr,
bool=
false) : ptr(in_ptr) {}
722 template <
typename T2>
Ptr(T2 * _ptr,
size_t,
bool) : ptr(_ptr) {}
727 bool IsNull()
const {
return ptr ==
nullptr; }
728 TYPE *
Raw() {
return ptr; }
729 const TYPE *
const Raw()
const {
return ptr; }
734 template <
typename... T>
735 void New(T &&... args) { ptr =
new TYPE(std::forward<T>(args)...); }
736 void NewArray(
size_t array_size) { ptr =
new TYPE[array_size]; }
742 return (
size_t)(ptr) >> shift;
764 const TYPE &
operator[](
size_t pos)
const {
return ptr[pos]; }
767 operator TYPE *() {
return ptr; }
769 operator bool() {
return ptr !=
nullptr; }
770 operator bool()
const {
return ptr !=
nullptr; }
775 bool operator<(const Ptr<TYPE> & in_ptr)
const {
return ptr < in_ptr.ptr; }
776 bool operator<=(const Ptr<TYPE> & in_ptr)
const {
return ptr <= in_ptr.ptr; }
781 bool operator==(
const TYPE * in_ptr)
const {
return ptr == in_ptr; }
782 bool operator!=(
const TYPE * in_ptr)
const {
return ptr != in_ptr; }
783 bool operator<(
const TYPE * in_ptr)
const {
return ptr < in_ptr; }
784 bool operator<=(
const TYPE * in_ptr)
const {
return ptr <= in_ptr; }
785 bool operator>(
const TYPE * in_ptr)
const {
return ptr > in_ptr; }
786 bool operator>=(
const TYPE * in_ptr)
const {
return ptr >= in_ptr; }
793 bool OK()
const {
return true; }
799 template <
typename T>
800 std::ostream & operator<<(std::ostream & out, const emp::Ptr<T> & ptr) {
807 template <
typename T,
typename... Ts>
822 template <
typename T,
typename... ARGS>
Ptr<T> NewPtr(ARGS &&... args) {
823 auto ptr =
new T(std::forward<ARGS>(args)...);
836 for (
size_t i = 0; i < in.size(); i++) out_ptrs[i] =
CopyPtr(in[i]);
843 for (
size_t i = 0; i < in.size(); i++) out_ptrs[i] = in[i]->Clone();
848 template <
typename T,
typename... ARGS>
Ptr<T> NewArrayPtr(
size_t array_size, ARGS &&... args) {
849 auto ptr =
new T[array_size];
856 return Ptr<T>(ptr, array_size,
true);
static constexpr size_t Log2(size_t x)
An anonymous log2 calculator for hashing below.
Definition: Ptr.h:36
Ptr< T > ToPtr(T *_in, bool own=false)
Convert a T* to a Ptr<T>. By default, don't track.
Definition: Ptr.h:816
size_t GetNumIDs() const
Lookup how many pointers are being tracked.
Definition: Ptr.h:183
int GetIDCount(size_t id) const
How many Ptr objects are associated with an ID?
Definition: Ptr.h:216
void Dec(size_t id)
Remove a pointer.
Definition: Ptr.h:100
bool operator>=(const Ptr< TYPE > &in_ptr) const
Definition: Ptr.h:778
static PtrTracker & Get()
Treat this class as a singleton with a single Get() method to retrieve it.
Definition: Ptr.h:167
PtrStatus
Definition: Ptr.h:43
emp::vector< Ptr< T > > CopyPtrs(const emp::vector< Ptr< T >> &in)
Copy a vector of objects pointed to; return a vector of Ptrs to the new copies.
Definition: Ptr.h:834
Ptr(T2 *_ptr, size_t, bool)
Construct from array.
Definition: Ptr.h:722
size_t GetCurID(const void *ptr)
Retrive the ID associated with a pointer.
Definition: Ptr.h:180
size_t DebugGetArrayBytes() const
Definition: Ptr.h:791
void Delete()
Definition: Ptr.h:737
bool DebugIsArray() const
Definition: Ptr.h:790
TYPE * Raw()
Definition: Ptr.h:728
size_t GetArrayBytes() const noexcept
If this ptr is to an array, how many bytes large is the array (may be different from size!) ...
Definition: Ptr.h:81
Ptr< TYPE > & operator=(const Ptr< TYPE > &_in)
Definition: Ptr.h:747
PtrInfo(const void *_ptr)
Definition: Ptr.h:53
const TYPE & operator*() const
Definition: Ptr.h:756
size_t Hash() const
Definition: Ptr.h:740
size_t New(const void *ptr)
This pointer was just created as a Ptr!
Definition: Ptr.h:222
std::istream & operator>>(std::istream &is, emp::Ptr< T > &ptr)
Definition: Ptr.h:808
Ptr< T > NewPtr(ARGS &&...args)
Create a new Ptr of the target type; use the args in the constructor.
Definition: Ptr.h:822
int GetCount() const noexcept
How many Ptr objects point to the associated position?
Definition: Ptr.h:78
int DebugGetCount() const
Definition: Ptr.h:789
bool IsArrayID(size_t id)
Is an ID associated with an array?
Definition: Ptr.h:210
Ptr()
Default constructor.
Definition: Ptr.h:718
~PtrTracker()
Definition: Ptr.h:147
Ptr< T > NewArrayPtr(size_t array_size, ARGS &&...args)
Create a pointer to an array of objects.
Definition: Ptr.h:848
const TYPE *const Raw() const
Definition: Ptr.h:729
Ptr< TYPE > & operator=(Ptr< TYPE > &&_in)
Definition: Ptr.h:748
size_t size() const
Definition: vector.h:151
emp::vector< Ptr< T > > ClonePtrs(const emp::vector< Ptr< T >> &in)
Copy a vector of objects pointed to by using their Clone() member function; return vector...
Definition: Ptr.h:841
void emplace_back(ARGS &&...args)
Definition: vector.h:219
bool operator<=(const TYPE *in_ptr) const
Definition: Ptr.h:784
PtrInfo & GetInfo(const void *ptr)
Get the info associated with an existing pointer.
Definition: Ptr.h:170
Ptr(std::nullptr_t)
From nullptr.
Definition: Ptr.h:724
A more dynamic replacement for standard library asserts.
bool OK() const
Definition: Ptr.h:793
PtrInfo & GetInfo(size_t id)
Definition: Ptr.h:171
bool operator!=(const Ptr< TYPE > &in_ptr) const
Definition: Ptr.h:774
bool operator>=(const TYPE *in_ptr) const
Definition: Ptr.h:786
size_t GetArrayBytes(size_t id) const
How big is an array associated with an ID?
Definition: Ptr.h:186
Ptr< TYPE > & operator=(T2 *_in)
Definition: Ptr.h:751
void DeleteArray()
Definition: Ptr.h:738
Ptr< T2 > DynamicCast()
Definition: Ptr.h:732
Ptr< T > TrackPtr(T *_in, bool own=true)
Convert a T* to a Ptr<T> that we DO track.
Definition: Ptr.h:819
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
~Ptr()
Destructor.
Definition: Ptr.h:725
const Ptr< const T2 > Cast() const
Definition: Ptr.h:731
TYPE *const operator->() const
Definition: Ptr.h:760
bool IsActiveID(size_t id)
Is a pointer id associated with a pointer that's active and ready to be used?
Definition: Ptr.h:203
bool GetPtrDebug()
Definition: Ptr.h:41
void SetPtrDebug(bool _d=true)
Definition: Ptr.h:40
Ptr(const Ptr< TYPE > &_in)
Copy constructor.
Definition: Ptr.h:719
Ptr< T > CopyPtr(Ptr< T > in)
Copy an object pointed to and return a Ptr to the copy.
Definition: Ptr.h:831
std::size_t Hash(const T &x)
Definition: meta.h:202
Ptr< T2 > Cast()
Definition: Ptr.h:730
bool operator>(const TYPE *in_ptr) const
Definition: Ptr.h:785
bool operator==(const Ptr< TYPE > &in_ptr) const
Definition: Ptr.h:773
const TYPE & operator[](size_t pos) const
Definition: Ptr.h:764
Ptr< TYPE > & operator=(Ptr< T2 > _in)
Definition: Ptr.h:752
bool DebugIsActive() const
Definition: Ptr.h:792
world_t element_type
Definition: Ptr.h:716
Ptr(Ptr< T2 > _in)
From compatible Ptr.
Definition: Ptr.h:723
Ptr(Ptr< TYPE > &&_in)
Move constructor.
Definition: Ptr.h:720
void IncID(size_t id)
Increment the nuber of Pointers associated with an ID.
Definition: Ptr.h:248
void DecID(size_t id)
Decrement the nuber of Pointers associated with an ID.
Definition: Ptr.h:255
A drop-in wrapper for std::vector; adds on bounds checking in debug mode.
If we are in emscripten, make sure to include the header.
Definition: array.h:37
bool HasPtr(const void *ptr) const
Determine if a pointer is being tracked.
Definition: Ptr.h:174
Facilitate tracking of all Ptr objects in this run.
Definition: Ptr.h:131
bool operator==(const TYPE *in_ptr) const
Definition: Ptr.h:781
Build a debug wrapper emp::vector around std::vector.
Definition: vector.h:42
bool IsActive(const void *ptr)
Is a pointer active and ready to be used?
Definition: Ptr.h:196
void SetArray(size_t bytes) noexcept
Denote that this pointer is an array.
Definition: Ptr.h:90
void NewArray(size_t array_size)
Definition: Ptr.h:736
#define emp_assert(...)
Definition: assert.h:199
bool operator>(const Ptr< TYPE > &in_ptr) const
Definition: Ptr.h:777
TYPE & operator*()
Definition: Ptr.h:755
void New(T &&...args)
Definition: Ptr.h:735
TYPE & operator[](size_t pos)
Definition: Ptr.h:763
size_t NewArray(const void *ptr, size_t array_bytes)
This pointer was just created as a Ptr ARRAY!
Definition: Ptr.h:240
~PtrInfo()
Definition: Ptr.h:70
void MarkDeleted()
Indicate that the associated position has been deleted.
Definition: Ptr.h:109
static bool ptr_debug
Definition: Ptr.h:38
PtrInfo(const void *_ptr, size_t _array_bytes)
Definition: Ptr.h:56
Ptr(T2 *in_ptr, bool=false)
Construct from raw ptr.
Definition: Ptr.h:721
void Inc(size_t id)
Add one more pointer.
Definition: Ptr.h:93
void MarkDeleted(size_t id)
Mark the pointers associated with this ID as deleted.
Definition: Ptr.h:265
bool IsNull() const
Definition: Ptr.h:727
TYPE * operator->()
Definition: Ptr.h:759
const void * GetPtr() const noexcept
What pointer does this one hold information about?
Definition: Ptr.h:75
bool operator<(const TYPE *in_ptr) const
Definition: Ptr.h:783
size_t operator()(const Ptr< TYPE > &t) const
Definition: Ptr.h:744
bool IsArray() const noexcept
Is this pointer pointing to an array?
Definition: Ptr.h:87
bool operator!=(const TYPE *in_ptr) const
Definition: Ptr.h:782
bool IsActive() const noexcept
Is this pointer currently valid to access?
Definition: Ptr.h:84
bool OK() const noexcept
Debug utility to determine if everything looks okay with this pointer's information.
Definition: Ptr.h:115
bool IsDeleted(size_t id) const
Check if an ID is for a pointer that has been deleted.
Definition: Ptr.h:189