You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							160 lines
						
					
					
						
							4.3 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							160 lines
						
					
					
						
							4.3 KiB
						
					
					
				
								#if !defined(__OBJECT_H)
							 | 
						|
								#define __OBJECT_H
							 | 
						|
								
							 | 
						|
								#include <atomic>
							 | 
						|
								
							 | 
						|
								/// Reference counted object base class
							 | 
						|
								class Object {
							 | 
						|
								public:
							 | 
						|
								    /// Default constructor
							 | 
						|
								    Object() { }
							 | 
						|
								
							 | 
						|
								    /// Copy constructor
							 | 
						|
								    Object(const Object &) : m_refCount(0) {}
							 | 
						|
								
							 | 
						|
									/// Return the current reference count
							 | 
						|
									int getRefCount() const { return m_refCount; };
							 | 
						|
								
							 | 
						|
									/// Increase the object's reference count by one
							 | 
						|
									void incRef() const { ++m_refCount; }
							 | 
						|
								
							 | 
						|
									/** \brief Decrease the reference count of
							 | 
						|
									 * the object and possibly deallocate it.
							 | 
						|
									 *
							 | 
						|
									 * The object will automatically be deallocated once
							 | 
						|
									 * the reference count reaches zero.
							 | 
						|
									 */
							 | 
						|
									void decRef(bool dealloc = true) const {
							 | 
						|
									    --m_refCount;
							 | 
						|
									    if (m_refCount == 0 && dealloc)
							 | 
						|
								            delete this;
							 | 
						|
								        else if (m_refCount < 0)
							 | 
						|
									        throw std::runtime_error("Internal error: reference count < 0!");
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    virtual std::string toString() const = 0;
							 | 
						|
								protected:
							 | 
						|
									/** \brief Virtual protected deconstructor.
							 | 
						|
									 * (Will only be called by \ref ref)
							 | 
						|
									 */
							 | 
						|
									virtual ~Object() { }
							 | 
						|
								private:
							 | 
						|
								    mutable std::atomic<int> m_refCount { 0 };
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * \brief Reference counting helper
							 | 
						|
								 *
							 | 
						|
								 * The \a ref refeference template is a simple wrapper to store a
							 | 
						|
								 * pointer to an object. It takes care of increasing and decreasing
							 | 
						|
								 * the reference count of the object. When the last reference goes
							 | 
						|
								 * out of scope, the associated object will be deallocated.
							 | 
						|
								 *
							 | 
						|
								 * \ingroup libcore
							 | 
						|
								 */
							 | 
						|
								template <typename T> class ref {
							 | 
						|
								public:
							 | 
						|
									/// Create a nullptr reference
							 | 
						|
								    ref() : m_ptr(nullptr) { std::cout << "Created empty ref" << std::endl; }
							 | 
						|
								
							 | 
						|
								    /// Construct a reference from a pointer
							 | 
						|
									ref(T *ptr) : m_ptr(ptr) {
							 | 
						|
								        std::cout << "Initialized ref from pointer " << ptr<< std::endl;
							 | 
						|
									    if (m_ptr) ((Object *) m_ptr)->incRef();
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									/// Copy constructor
							 | 
						|
								    ref(const ref &r) : m_ptr(r.m_ptr) {
							 | 
						|
								        std::cout << "Initialized ref from ref " << r.m_ptr << std::endl;
							 | 
						|
								        if (m_ptr)
							 | 
						|
								            ((Object *) m_ptr)->incRef();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /// Move constructor
							 | 
						|
								    ref(ref &&r) : m_ptr(r.m_ptr) {
							 | 
						|
								        std::cout << "Initialized ref with move from ref " << r.m_ptr << std::endl;
							 | 
						|
								        r.m_ptr = nullptr; 
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /// Destroy this reference
							 | 
						|
								    ~ref() {
							 | 
						|
								        std::cout << "Destructing ref " << m_ptr << std::endl;
							 | 
						|
								        if (m_ptr)
							 | 
						|
								            ((Object *) m_ptr)->decRef();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /// Move another reference into the current one
							 | 
						|
									ref& operator=(ref&& r) {
							 | 
						|
								        std::cout << "Move-assigning ref " << r.m_ptr << std::endl;
							 | 
						|
										if (*this == r)
							 | 
						|
											return *this;
							 | 
						|
										if (m_ptr)
							 | 
						|
											((Object *) m_ptr)->decRef();
							 | 
						|
										m_ptr = r.m_ptr;
							 | 
						|
										r.m_ptr = nullptr;
							 | 
						|
										return *this;
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									/// Overwrite this reference with another reference
							 | 
						|
									ref& operator=(const ref& r) {
							 | 
						|
								        std::cout << "Assigning ref " << r.m_ptr << std::endl;
							 | 
						|
										if (m_ptr == r.m_ptr)
							 | 
						|
											return *this;
							 | 
						|
										if (m_ptr)
							 | 
						|
											((Object *) m_ptr)->decRef();
							 | 
						|
										m_ptr = r.m_ptr;
							 | 
						|
										if (m_ptr)
							 | 
						|
											((Object *) m_ptr)->incRef();
							 | 
						|
										return *this;
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									/// Overwrite this reference with a pointer to another object
							 | 
						|
									ref& operator=(T *ptr) {
							 | 
						|
								        std::cout << "Assigning ptr " << ptr << " to ref" << std::endl;
							 | 
						|
										if (m_ptr == ptr)
							 | 
						|
											return *this;
							 | 
						|
										if (m_ptr)
							 | 
						|
											((Object *) m_ptr)->decRef();
							 | 
						|
										m_ptr = ptr;
							 | 
						|
										if (m_ptr)
							 | 
						|
											((Object *) m_ptr)->incRef();
							 | 
						|
										return *this;
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									/// Compare this reference with another reference
							 | 
						|
									bool operator==(const ref &r) const { return m_ptr == r.m_ptr; }
							 | 
						|
								
							 | 
						|
									/// Compare this reference with another reference
							 | 
						|
									bool operator!=(const ref &r) const { return m_ptr != r.m_ptr; }
							 | 
						|
								
							 | 
						|
									/// Compare this reference with a pointer
							 | 
						|
									bool operator==(const T* ptr) const { return m_ptr == ptr; }
							 | 
						|
								
							 | 
						|
									/// Compare this reference with a pointer
							 | 
						|
									bool operator!=(const T* ptr) const { return m_ptr != ptr; }
							 | 
						|
								
							 | 
						|
									/// Access the object referenced by this reference
							 | 
						|
									T* operator->() { return m_ptr; }
							 | 
						|
								
							 | 
						|
									/// Access the object referenced by this reference
							 | 
						|
									const T* operator->() const { return m_ptr; }
							 | 
						|
								
							 | 
						|
									/// Return a C++ reference to the referenced object
							 | 
						|
									T& operator*() { return *m_ptr; }
							 | 
						|
								
							 | 
						|
									/// Return a const C++ reference to the referenced object
							 | 
						|
									const T& operator*() const { return *m_ptr; }
							 | 
						|
								
							 | 
						|
									/// Return a pointer to the referenced object
							 | 
						|
									operator T* () { return m_ptr; }
							 | 
						|
								
							 | 
						|
									/// Return a const pointer to the referenced object
							 | 
						|
									T* get() { return m_ptr; }
							 | 
						|
								
							 | 
						|
									/// Return a pointer to the referenced object
							 | 
						|
									const T* get() const { return m_ptr; }
							 | 
						|
								private:
							 | 
						|
									T *m_ptr;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								#endif /* __OBJECT_H */
							 |