/**************************************************************************************************************************** Pointer.h This library provides function templates to better support C++ functional programming across platforms. Based on Vlpp library (https://github.com/vczh-libraries/Vlpp) and Marcus Rugger functional-vlpp library (https://github.com/marcusrugger/functional-vlpp) Built by Khoi Hoang (https://github.com/khoih-prog/functional-vlpp) Licensed under MIT license Original author Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::Basic Classes: Ptr :Smart pointer Version: 1.0.2 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K Hoang 13/02/2019 Initial coding, testing and supporting AVR architecture 1.0.1 K Hoang 01/03/2020 Add support for STM32 and all other architectures. 1.0.2 K Hoang 21/02/2021 Clear compiler warnings *****************************************************************************************************************************/ #pragma once #ifndef VCZH_POINTER #define VCZH_POINTER #include "Basic.h" namespace vl { /*********************************************************************** ReferenceCounterOperator ***********************************************************************/ /// The strategy to get the pointer to the reference counter from an object. If you get the same pointer multiple times /// from the same object by calling [M:vl.ReferenceCounterOperator`2.CreateCounter], than it is safe to convert a object pointer /// to a [T:vl.Ptr`1]. Currently for reflectable C++ types which inherit from [T:vl.reflection.DescriptableObject] it is yet. /// For others it is no. /// The type of the object. /// [T:vl.Ptr`1] will always use [T:vl.YesType] as the second type parameter. This parameter is useful /// when you want to do partial specialization in the SFINAE way. template struct ReferenceCounterOperator { /// Create a pointer to the reference counter from an object. /// The pointer to the reference counter. /// The object. static __forceinline volatile vint* CreateCounter(T* reference) { (void) reference; return new vint(0); } /// Destroy a pointer to the reference counter from an object. /// The pointer to the reference counter. /// The object. static __forceinline void DeleteReference(volatile vint* counter, void* reference) { delete counter; delete (T*)reference; } }; /*********************************************************************** Smart Ptr Class ***********************************************************************/ /// A smart pointer. It is always safe to convert a pointer to an object to a smart pointer once. If you do it multiple times, /// it may be wrong due to different implementation of [T:vl.ReferenceCounterOperator`2]. In case of wrong, disposing the smart pointer /// will cause an access violation. /// The type of the object. template class Ptr { template friend class Ptr; protected: typedef void (*Destructor)(volatile vint*, void*); volatile vint* counter; T* reference; void* originalReference; Destructor originalDestructor; void Inc() { if (counter) { INCRC(counter); } } void Dec() { if (counter) { if (DECRC(counter) == 0) { originalDestructor(counter, originalReference); counter = 0; reference = 0; originalReference = 0; originalDestructor = 0; } } } volatile vint* Counter()const { return counter; } Ptr(volatile vint* _counter, T* _reference, void* _originalReference, Destructor _originalDestructor) : counter(_counter) , reference(_reference) , originalReference(_originalReference) , originalDestructor(_originalDestructor) { Inc(); } public: /// Create a null pointer. Ptr() : counter(0) , reference(0) , originalReference(0) , originalDestructor(0) { } /// Convert a pointer to an object to a smart pointer. /// The pointer to the object. Ptr(T* pointer) : counter(0) , reference(0) , originalReference(0) , originalDestructor(0) { if (pointer) { counter = ReferenceCounterOperator::CreateCounter(pointer); reference = pointer; originalReference = pointer; originalDestructor = &ReferenceCounterOperator::DeleteReference; Inc(); } } /// Copy a smart pointer. /// The smart pointer to copy. Ptr(const Ptr& pointer) : counter(pointer.counter) , reference(pointer.reference) , originalReference(pointer.originalReference) , originalDestructor(pointer.originalDestructor) { Inc(); } /// Move a smart pointer. /// The smart pointer to Move. Ptr(Ptr&& pointer) : counter(pointer.counter) , reference(pointer.reference) , originalReference(pointer.originalReference) , originalDestructor(pointer.originalDestructor) { pointer.counter = 0; pointer.reference = 0; pointer.originalReference = 0; pointer.originalDestructor = 0; } /// Cast a smart pointer. /// The type of the object before casting. /// The smart pointer to cast. template Ptr(const Ptr& pointer) : counter(0) , reference(0) , originalReference(0) , originalDestructor(0) { T* converted = pointer.Obj(); if (converted) { counter = pointer.Counter(); reference = converted; originalReference = pointer.originalReference; originalDestructor = pointer.originalDestructor; Inc(); } } ~Ptr() { Dec(); } /// Cast a smart pointer. /// The type of the object after casting. /// The casted smart pointer. Returns null if failed. template Ptr Cast()const { C* converted = dynamic_cast(reference); return Ptr((converted ? counter : 0), converted, originalReference, originalDestructor); } /// Convert a pointer to an object to a smart pointer. /// The converted smart pointer. /// The pointer to the object. Ptr& operator=(T* pointer) { Dec(); if (pointer) { counter = ReferenceCounterOperator::CreateCounter(pointer); reference = pointer; originalReference = pointer; originalDestructor = &ReferenceCounterOperator::DeleteReference; Inc(); } else { counter = 0; reference = 0; originalReference = 0; originalDestructor = 0; } return *this; } /// Copy a smart pointer. /// The copied smart pointer. /// The smart pointer to copy. Ptr& operator=(const Ptr& pointer) { if (this != &pointer) { Dec(); counter = pointer.counter; reference = pointer.reference; originalReference = pointer.originalReference; originalDestructor = pointer.originalDestructor; Inc(); } return *this; } /// Move a smart pointer. /// The moved smart pointer. /// The smart pointer to Move. Ptr& operator=(Ptr&& pointer) { if (this != &pointer) { Dec(); counter = pointer.counter; reference = pointer.reference; originalReference = pointer.originalReference; originalDestructor = pointer.originalDestructor; pointer.counter = 0; pointer.reference = 0; pointer.originalReference = 0; pointer.originalDestructor = 0; } return *this; } /// Cast a smart pointer. /// The type of the object before casting. /// The smart pointer after casting. /// The smart pointer to cast. template Ptr& operator=(const Ptr& pointer) { T* converted = pointer.Obj(); Dec(); if (converted) { counter = pointer.counter; reference = converted; originalReference = pointer.originalReference; originalDestructor = pointer.originalDestructor; Inc(); } else { counter = 0; reference = 0; originalReference = 0; originalDestructor = 0; } return *this; } bool operator==(const T* pointer)const { return reference == pointer; } bool operator!=(const T* pointer)const { return reference != pointer; } bool operator>(const T* pointer)const { return reference > pointer; } bool operator>=(const T* pointer)const { return reference >= pointer; } bool operator<(const T* pointer)const { return reference < pointer; } bool operator<=(const T* pointer)const { return reference <= pointer; } bool operator==(const Ptr& pointer)const { return reference == pointer.reference; } bool operator!=(const Ptr& pointer)const { return reference != pointer.reference; } bool operator>(const Ptr& pointer)const { return reference > pointer.reference; } bool operator>=(const Ptr& pointer)const { return reference >= pointer.reference; } bool operator<(const Ptr& pointer)const { return reference < pointer.reference; } bool operator<=(const Ptr& pointer)const { return reference <= pointer.reference; } /// Test if it is a null pointer. /// Returns true if it is not null. operator bool()const { return reference != 0; } /// Get the pointer to the object. /// The pointer to the object. T* Obj()const { return reference; } /// Get the pointer to the object. /// The pointer to the object. T* operator->()const { return reference; } }; /*********************************************************************** ComPtr ***********************************************************************/ template class ComPtr { protected: volatile vint* counter; T* reference; void Inc() { if (counter) { INCRC(counter); } } void Dec() { if (counter) { if (DECRC(counter) == 0) { delete counter; reference->Release(); counter = 0; reference = 0; } } } volatile vint* Counter()const { return counter; } ComPtr(volatile vint* _counter, T* _reference) : counter(_counter) , reference(_reference) { Inc(); } public: ComPtr() { counter = 0; reference = 0; } ComPtr(T* pointer) { if (pointer) { counter = new volatile vint(1); reference = pointer; } else { counter = 0; reference = 0; } } ComPtr(const ComPtr& pointer) { counter = pointer.counter; reference = pointer.reference; Inc(); } ComPtr(ComPtr&& pointer) { counter = pointer.counter; reference = pointer.reference; pointer.counter = 0; pointer.reference = 0; } ~ComPtr() { Dec(); } ComPtr& operator=(T* pointer) { Dec(); if (pointer) { counter = new vint(1); reference = pointer; } else { counter = 0; reference = 0; } return *this; } ComPtr& operator=(const ComPtr& pointer) { if (this != &pointer) { Dec(); counter = pointer.counter; reference = pointer.reference; Inc(); } return *this; } ComPtr& operator=(ComPtr&& pointer) { if (this != &pointer) { Dec(); counter = pointer.counter; reference = pointer.reference; pointer.counter = 0; pointer.reference = 0; } return *this; } bool operator==(const T* pointer)const { return reference == pointer; } bool operator!=(const T* pointer)const { return reference != pointer; } bool operator>(const T* pointer)const { return reference > pointer; } bool operator>=(const T* pointer)const { return reference >= pointer; } bool operator<(const T* pointer)const { return reference < pointer; } bool operator<=(const T* pointer)const { return reference <= pointer; } bool operator==(const ComPtr& pointer)const { return reference == pointer.reference; } bool operator!=(const ComPtr& pointer)const { return reference != pointer.reference; } bool operator>(const ComPtr& pointer)const { return reference > pointer.reference; } bool operator>=(const ComPtr& pointer)const { return reference >= pointer.reference; } bool operator<(const ComPtr& pointer)const { return reference < pointer.reference; } bool operator<=(const ComPtr& pointer)const { return reference <= pointer.reference; } operator bool()const { return reference != 0; } T* Obj()const { return reference; } T* operator->()const { return reference; } }; template Ptr MakePtr(TArgs ...args) { return new T(args...); } /*********************************************************************** Traits ***********************************************************************/ template struct KeyType> { typedef T* Type; static T* GetKeyValue(const Ptr& key) { return key.Obj(); } }; template struct POD> { static const bool Result = false; }; template struct KeyType> { typedef T* Type; static T* GetKeyValue(const ComPtr& key) { return key.Obj(); } }; template struct POD> { static const bool Result = false; }; } // namespace vl #endif // VCZH_POINTER