#ifndef __FENNIX_KERNEL_STD_SMART_POINTER_H__ #define __FENNIX_KERNEL_STD_SMART_POINTER_H__ #include #include // show debug messages // #define DEBUG_SMARTPOINTERS 1 #ifdef DEBUG_SMARTPOINTERS #define spdbg(m, ...) debug(m, ##__VA_ARGS__) #else #define spdbg(m, ...) #endif namespace std { /** * @brief A smart pointer class * * This class is a smart pointer class. It is used to manage the lifetime of * objects. It is a reference counted pointer, so when the last reference to * the object is removed, the object is deleted. * * Basic Usage: * smart_ptr pointer(new char()); * *pointer = 'a'; * printf("%c", *pointer); // Prints "a" */ template class smart_ptr { T *RealPointer; public: explicit smart_ptr(T *Pointer = nullptr) { spdbg("Smart pointer created (%#lx)", this->RealPointer); this->RealPointer = Pointer; } ~smart_ptr() { spdbg("Smart pointer deleted (%#lx)", this->RealPointer); delete this->RealPointer, this->RealPointer = nullptr; } T &operator*() { spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer); return *this->RealPointer; } T *operator->() { spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer); return this->RealPointer; } T *get() { spdbg("Smart pointer returned (%#lx)", this->RealPointer); return this->RealPointer; } }; template class auto_ptr { }; template class unique_ptr { }; template class weak_ptr { }; template class shared_ptr { private: class counter { private: unsigned int RefCount{}; public: counter() : RefCount(0) { spdbg("Counter %#lx created", this); }; counter(const counter &) = delete; counter &operator=(const counter &) = delete; ~counter() { spdbg("Counter %#lx deleted", this); } void reset() { this->RefCount = 0; spdbg("reset"); } unsigned int get() { return this->RefCount; spdbg("return"); } void operator++() { this->RefCount++; spdbg("increment"); } void operator++(int) { this->RefCount++; spdbg("increment"); } void operator--() { this->RefCount--; spdbg("decrement"); } void operator--(int) { this->RefCount--; spdbg("decrement"); } }; counter *ReferenceCounter; T *RealPointer; public: explicit shared_ptr(T *Pointer = nullptr) { this->RealPointer = Pointer; this->ReferenceCounter = new counter(); spdbg("[%#lx] Shared pointer created (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter); if (Pointer) (*this->ReferenceCounter)++; } shared_ptr(shared_ptr &SPtr) { spdbg("[%#lx] Shared pointer copied (ptr=%#lx, ref=%#lx)", this, SPtr.RealPointer, SPtr.ReferenceCounter); this->RealPointer = SPtr.RealPointer; this->ReferenceCounter = SPtr.ReferenceCounter; (*this->ReferenceCounter)++; } ~shared_ptr() { spdbg("[%#lx] Shared pointer destructor called", this); (*this->ReferenceCounter)--; if (this->ReferenceCounter->get() == 0) { spdbg("[%#lx] Shared pointer deleted (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter); delete this->ReferenceCounter, this->ReferenceCounter = nullptr; delete this->RealPointer, this->RealPointer = nullptr; } } unsigned int get_count() { spdbg("[%#lx] Shared pointer count (%d)", this, this->ReferenceCounter->get()); return this->ReferenceCounter->get(); } T *get() { spdbg("[%#lx] Shared pointer get (%#lx)", this, this->RealPointer); return this->RealPointer; } T &operator*() { spdbg("[%#lx] Shared pointer dereference (ptr*=%#lx)", this, *this->RealPointer); return *this->RealPointer; } T *operator->() { spdbg("[%#lx] Shared pointer dereference (ptr->%#lx)", this, this->RealPointer); return this->RealPointer; } void reset(T *Pointer = nullptr) { if (this->RealPointer == Pointer) return; spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter); (*this->ReferenceCounter)--; if (this->ReferenceCounter->get() == 0) { delete this->RealPointer; delete this->ReferenceCounter; } this->RealPointer = Pointer; this->ReferenceCounter = new counter(); if (Pointer) (*this->ReferenceCounter)++; } void reset() { spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter); if (this->ReferenceCounter->get() == 1) { delete this->RealPointer, this->RealPointer = nullptr; delete this->ReferenceCounter, this->ReferenceCounter = nullptr; } else { (*this->ReferenceCounter)--; } } void swap(shared_ptr &Other) { spdbg("[%#lx] Shared pointer swap (ptr=%#lx, ref=%#lx <=> ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter, Other.RealPointer, Other.ReferenceCounter); T *tempRealPointer = this->RealPointer; counter *tempReferenceCounter = this->ReferenceCounter; this->RealPointer = Other.RealPointer; this->ReferenceCounter = Other.ReferenceCounter; Other.RealPointer = tempRealPointer; Other.ReferenceCounter = tempReferenceCounter; } }; template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; template using remove_reference_t = typename remove_reference::type; template T &&forward(remove_reference_t &t) { return static_cast(t); }; template T &&forward(remove_reference_t &&t) { return static_cast(t); }; template shared_ptr make_shared(Args &&...args) { return shared_ptr(new T(forward(args)...)); }; template smart_ptr make_smart(Args &&...args) { return smart_ptr(new T(forward(args)...)); }; } #endif // !__FENNIX_KERNEL_STD_SMART_POINTER_H__