object.h revision 11986
113531Sjairo.balart@metempsy.com#if !defined(__OBJECT_H) 213531Sjairo.balart@metempsy.com#define __OBJECT_H 313531Sjairo.balart@metempsy.com 413531Sjairo.balart@metempsy.com#include <atomic> 513531Sjairo.balart@metempsy.com#include "constructor_stats.h" 613531Sjairo.balart@metempsy.com 713531Sjairo.balart@metempsy.com/// Reference counted object base class 813531Sjairo.balart@metempsy.comclass Object { 913531Sjairo.balart@metempsy.compublic: 1013531Sjairo.balart@metempsy.com /// Default constructor 1113531Sjairo.balart@metempsy.com Object() { print_default_created(this); } 1213531Sjairo.balart@metempsy.com 1313531Sjairo.balart@metempsy.com /// Copy constructor 1413531Sjairo.balart@metempsy.com Object(const Object &) : m_refCount(0) { print_copy_created(this); } 1513531Sjairo.balart@metempsy.com 1613531Sjairo.balart@metempsy.com /// Return the current reference count 1713531Sjairo.balart@metempsy.com int getRefCount() const { return m_refCount; }; 1813531Sjairo.balart@metempsy.com 1913531Sjairo.balart@metempsy.com /// Increase the object's reference count by one 2013531Sjairo.balart@metempsy.com void incRef() const { ++m_refCount; } 2113531Sjairo.balart@metempsy.com 2213531Sjairo.balart@metempsy.com /** \brief Decrease the reference count of 2313531Sjairo.balart@metempsy.com * the object and possibly deallocate it. 2413531Sjairo.balart@metempsy.com * 2513531Sjairo.balart@metempsy.com * The object will automatically be deallocated once 2613531Sjairo.balart@metempsy.com * the reference count reaches zero. 2713531Sjairo.balart@metempsy.com */ 2813531Sjairo.balart@metempsy.com void decRef(bool dealloc = true) const { 2913531Sjairo.balart@metempsy.com --m_refCount; 3013531Sjairo.balart@metempsy.com if (m_refCount == 0 && dealloc) 3113531Sjairo.balart@metempsy.com delete this; 3213531Sjairo.balart@metempsy.com else if (m_refCount < 0) 3313531Sjairo.balart@metempsy.com throw std::runtime_error("Internal error: reference count < 0!"); 3413531Sjairo.balart@metempsy.com } 3513531Sjairo.balart@metempsy.com 3613531Sjairo.balart@metempsy.com virtual std::string toString() const = 0; 3713531Sjairo.balart@metempsy.comprotected: 3813531Sjairo.balart@metempsy.com /** \brief Virtual protected deconstructor. 3913531Sjairo.balart@metempsy.com * (Will only be called by \ref ref) 4013531Sjairo.balart@metempsy.com */ 4113531Sjairo.balart@metempsy.com virtual ~Object() { print_destroyed(this); } 4213531Sjairo.balart@metempsy.comprivate: 4313531Sjairo.balart@metempsy.com mutable std::atomic<int> m_refCount { 0 }; 4413531Sjairo.balart@metempsy.com}; 4513531Sjairo.balart@metempsy.com 4613531Sjairo.balart@metempsy.com// Tag class used to track constructions of ref objects. When we track constructors, below, we 4713531Sjairo.balart@metempsy.com// track and print out the actual class (e.g. ref<MyObject>), and *also* add a fake tracker for 4813531Sjairo.balart@metempsy.com// ref_tag. This lets us check that the total number of ref<Anything> constructors/destructors is 4913531Sjairo.balart@metempsy.com// correct without having to check each individual ref<Whatever> type individually. 5013531Sjairo.balart@metempsy.comclass ref_tag {}; 5113531Sjairo.balart@metempsy.com 5213531Sjairo.balart@metempsy.com/** 5313531Sjairo.balart@metempsy.com * \brief Reference counting helper 5413531Sjairo.balart@metempsy.com * 5513531Sjairo.balart@metempsy.com * The \a ref refeference template is a simple wrapper to store a 5613531Sjairo.balart@metempsy.com * pointer to an object. It takes care of increasing and decreasing 5713531Sjairo.balart@metempsy.com * the reference count of the object. When the last reference goes 5813531Sjairo.balart@metempsy.com * out of scope, the associated object will be deallocated. 5913531Sjairo.balart@metempsy.com * 6013531Sjairo.balart@metempsy.com * \ingroup libcore 6113531Sjairo.balart@metempsy.com */ 6213531Sjairo.balart@metempsy.comtemplate <typename T> class ref { 6313531Sjairo.balart@metempsy.compublic: 6413531Sjairo.balart@metempsy.com /// Create a nullptr reference 6513531Sjairo.balart@metempsy.com ref() : m_ptr(nullptr) { print_default_created(this); track_default_created((ref_tag*) this); } 6613531Sjairo.balart@metempsy.com 6713826Sgiacomo.travaglini@arm.com /// Construct a reference from a pointer 6813826Sgiacomo.travaglini@arm.com ref(T *ptr) : m_ptr(ptr) { 6913826Sgiacomo.travaglini@arm.com if (m_ptr) ((Object *) m_ptr)->incRef(); 7013826Sgiacomo.travaglini@arm.com 7113826Sgiacomo.travaglini@arm.com print_created(this, "from pointer", m_ptr); track_created((ref_tag*) this, "from pointer"); 7213826Sgiacomo.travaglini@arm.com 7313531Sjairo.balart@metempsy.com } 7413760Sjairo.balart@metempsy.com 7513531Sjairo.balart@metempsy.com /// Copy constructor 7613531Sjairo.balart@metempsy.com ref(const ref &r) : m_ptr(r.m_ptr) { 7713531Sjairo.balart@metempsy.com if (m_ptr) 7813531Sjairo.balart@metempsy.com ((Object *) m_ptr)->incRef(); 7913531Sjairo.balart@metempsy.com 8013531Sjairo.balart@metempsy.com print_copy_created(this, "with pointer", m_ptr); track_copy_created((ref_tag*) this); 8113531Sjairo.balart@metempsy.com } 8213531Sjairo.balart@metempsy.com 8313531Sjairo.balart@metempsy.com /// Move constructor 8413531Sjairo.balart@metempsy.com ref(ref &&r) : m_ptr(r.m_ptr) { 8513531Sjairo.balart@metempsy.com r.m_ptr = nullptr; 8613531Sjairo.balart@metempsy.com 8713531Sjairo.balart@metempsy.com print_move_created(this, "with pointer", m_ptr); track_move_created((ref_tag*) this); 8813760Sjairo.balart@metempsy.com } 8913531Sjairo.balart@metempsy.com 9013531Sjairo.balart@metempsy.com /// Destroy this reference 9113531Sjairo.balart@metempsy.com ~ref() { 9213531Sjairo.balart@metempsy.com if (m_ptr) 9313531Sjairo.balart@metempsy.com ((Object *) m_ptr)->decRef(); 9413531Sjairo.balart@metempsy.com 9513531Sjairo.balart@metempsy.com print_destroyed(this); track_destroyed((ref_tag*) this); 9613531Sjairo.balart@metempsy.com } 9713531Sjairo.balart@metempsy.com 9813531Sjairo.balart@metempsy.com /// Move another reference into the current one 9913531Sjairo.balart@metempsy.com ref& operator=(ref&& r) { 10013531Sjairo.balart@metempsy.com print_move_assigned(this, "pointer", r.m_ptr); track_move_assigned((ref_tag*) this); 10113580Sgabeblack@google.com 10213531Sjairo.balart@metempsy.com if (*this == r) 10313531Sjairo.balart@metempsy.com return *this; 10413580Sgabeblack@google.com if (m_ptr) 10513531Sjairo.balart@metempsy.com ((Object *) m_ptr)->decRef(); 10613531Sjairo.balart@metempsy.com m_ptr = r.m_ptr; 10713531Sjairo.balart@metempsy.com r.m_ptr = nullptr; 10813531Sjairo.balart@metempsy.com return *this; 10913760Sjairo.balart@metempsy.com } 11013531Sjairo.balart@metempsy.com 11113531Sjairo.balart@metempsy.com /// Overwrite this reference with another reference 11213531Sjairo.balart@metempsy.com ref& operator=(const ref& r) { 11313531Sjairo.balart@metempsy.com print_copy_assigned(this, "pointer", r.m_ptr); track_copy_assigned((ref_tag*) this); 11413531Sjairo.balart@metempsy.com 11513531Sjairo.balart@metempsy.com if (m_ptr == r.m_ptr) 11613531Sjairo.balart@metempsy.com return *this; 11713531Sjairo.balart@metempsy.com if (m_ptr) 11813531Sjairo.balart@metempsy.com ((Object *) m_ptr)->decRef(); 11913531Sjairo.balart@metempsy.com m_ptr = r.m_ptr; 12013531Sjairo.balart@metempsy.com if (m_ptr) 12113531Sjairo.balart@metempsy.com ((Object *) m_ptr)->incRef(); 12213531Sjairo.balart@metempsy.com return *this; 12313531Sjairo.balart@metempsy.com } 12413531Sjairo.balart@metempsy.com 12513531Sjairo.balart@metempsy.com /// Overwrite this reference with a pointer to another object 12613531Sjairo.balart@metempsy.com ref& operator=(T *ptr) { 12713531Sjairo.balart@metempsy.com print_values(this, "assigned pointer"); track_values((ref_tag*) this, "assigned pointer"); 12813531Sjairo.balart@metempsy.com 12913531Sjairo.balart@metempsy.com if (m_ptr == ptr) 13013531Sjairo.balart@metempsy.com return *this; 13113531Sjairo.balart@metempsy.com if (m_ptr) 13213760Sjairo.balart@metempsy.com ((Object *) m_ptr)->decRef(); 13313531Sjairo.balart@metempsy.com m_ptr = ptr; 13413531Sjairo.balart@metempsy.com if (m_ptr) 13513531Sjairo.balart@metempsy.com ((Object *) m_ptr)->incRef(); 13613531Sjairo.balart@metempsy.com return *this; 13713531Sjairo.balart@metempsy.com } 13813531Sjairo.balart@metempsy.com 13913531Sjairo.balart@metempsy.com /// Compare this reference with another reference 14013531Sjairo.balart@metempsy.com bool operator==(const ref &r) const { return m_ptr == r.m_ptr; } 14113531Sjairo.balart@metempsy.com 14213531Sjairo.balart@metempsy.com /// Compare this reference with another reference 14313531Sjairo.balart@metempsy.com bool operator!=(const ref &r) const { return m_ptr != r.m_ptr; } 14413531Sjairo.balart@metempsy.com 14513531Sjairo.balart@metempsy.com /// Compare this reference with a pointer 14613531Sjairo.balart@metempsy.com bool operator==(const T* ptr) const { return m_ptr == ptr; } 14713531Sjairo.balart@metempsy.com 14813531Sjairo.balart@metempsy.com /// Compare this reference with a pointer 14913531Sjairo.balart@metempsy.com bool operator!=(const T* ptr) const { return m_ptr != ptr; } 15013531Sjairo.balart@metempsy.com 15113531Sjairo.balart@metempsy.com /// Access the object referenced by this reference 15213531Sjairo.balart@metempsy.com T* operator->() { return m_ptr; } 15313531Sjairo.balart@metempsy.com 15413531Sjairo.balart@metempsy.com /// Access the object referenced by this reference 15513760Sjairo.balart@metempsy.com const T* operator->() const { return m_ptr; } 15613531Sjairo.balart@metempsy.com 15713531Sjairo.balart@metempsy.com /// Return a C++ reference to the referenced object 15813531Sjairo.balart@metempsy.com T& operator*() { return *m_ptr; } 15913760Sjairo.balart@metempsy.com 16013531Sjairo.balart@metempsy.com /// Return a const C++ reference to the referenced object 16113531Sjairo.balart@metempsy.com const T& operator*() const { return *m_ptr; } 16213531Sjairo.balart@metempsy.com 16313531Sjairo.balart@metempsy.com /// Return a pointer to the referenced object 16413531Sjairo.balart@metempsy.com operator T* () { return m_ptr; } 16513760Sjairo.balart@metempsy.com 16613531Sjairo.balart@metempsy.com /// Return a const pointer to the referenced object 16713531Sjairo.balart@metempsy.com T* get() { return m_ptr; } 16813531Sjairo.balart@metempsy.com 16913760Sjairo.balart@metempsy.com /// Return a pointer to the referenced object 17013531Sjairo.balart@metempsy.com const T* get() const { return m_ptr; } 17113531Sjairo.balart@metempsy.comprivate: 17213531Sjairo.balart@metempsy.com T *m_ptr; 17313531Sjairo.balart@metempsy.com}; 17413531Sjairo.balart@metempsy.com 17513760Sjairo.balart@metempsy.com#endif /* __OBJECT_H */ 17613760Sjairo.balart@metempsy.com