diff --git a/Plugins/org.blueberry.core.runtime/src/berryObject.cpp b/Plugins/org.blueberry.core.runtime/src/berryObject.cpp index 1d1b428357..2b1e46ea51 100644 --- a/Plugins/org.blueberry.core.runtime/src/berryObject.cpp +++ b/Plugins/org.blueberry.core.runtime/src/berryObject.cpp @@ -1,285 +1,285 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "berryObject.h" #ifdef BLUEBERRY_DEBUG_SMARTPOINTER #include "berryDebugUtil.h" #endif #include "berryLog.h" #include "berryReflection.h" #include #include #include #include namespace berry { void Object::Delete() { this->UnRegister(); } #ifdef _WIN32 void* Object ::operator new(size_t n) { return new char[n]; } void* Object ::operator new[](size_t n) { return new char[n]; } void Object ::operator delete(void* m) { delete [] (char*)m; } void Object ::operator delete[](void* m, size_t) { delete [] (char*)m; } #endif const char* Object::GetStaticClassName() { return "berry::Object"; } QString Object::GetClassName() const { return Reflection::DemangleName(typeid(*this).name()); } Reflection::TypeInfo Object::GetStaticTypeInfo() { return Reflection::TypeInfo::New(); } Reflection::TypeInfo Object::GetTypeInfo() const { return Self::GetStaticTypeInfo(); } QList Object::GetStaticSuperclasses() { return QList(); } QList Object::GetSuperclasses() const { return GetStaticSuperclasses(); } QDebug Object::Print(QDebug os, Indent indent) const { os = this->PrintHeader(os, indent); os = this->PrintSelf(os, indent.GetNextIndent()); return this->PrintTrailer(os, indent); } QString Object::ToString() const { QString str; QDebug ss(&str); this->Print(ss); return str; } uint Object::HashCode() const { return qHash(this); } bool Object::operator<(const Object* o) const { return this < o; } void Object::Register() const { m_ReferenceCount.ref(); } void Object::UnRegister(bool del) const { if (!m_ReferenceCount.deref() && del) { delete this; } } void Object::SetReferenceCount(int ref) { QMutexLocker lock(&m_ReferenceCountLock); - m_ReferenceCount.store(ref); + m_ReferenceCount.storeRelaxed(ref); if (ref == 0) { delete this; } } bool Object::operator==(const Object* o) const { return this == o; } #ifdef BLUEBERRY_DEBUG_SMARTPOINTER unsigned int Object::GetTraceId() const { return m_TraceId; } unsigned int& Object::GetTraceIdCounter() const { static unsigned int traceId = 0; return traceId; } #endif Object::Object() : m_ReferenceCount(0) { #ifdef BLUEBERRY_DEBUG_SMARTPOINTER unsigned int& id = GetTraceIdCounter(); m_TraceId = ++id; DebugUtil::RegisterObject(this); #endif } Object::~Object() { /** * warn user if reference counting is on and the object is being referenced * by another object. */ - if (m_ReferenceCount.load() > 0) + if (m_ReferenceCount.loadRelaxed() > 0) { // A general exception safety rule is that destructors should // never throw. Something is wrong with a program that reaches // this point anyway. Also this is the least-derived class so the // whole object has been destroyed by this point anyway. Just // issue a warning. BERRY_WARN << "WARNING: In " __FILE__ ", line " << __LINE__ << "\n" << this->GetClassName() << " (" << this << "): Trying to delete object with non-zero reference count."; } /** * notifies the registered functions that the object is being destroyed */ m_DestroyMessage.Send(); #ifdef BLUEBERRY_DEBUG_SMARTPOINTER DebugUtil::UnregisterObject(this); #endif } QDebug Object::PrintSelf(QDebug os, Indent Indent) const { QString demangledName = Reflection::DemangleName(typeid(*this).name()); os << Indent << "RTTI typeinfo: " << demangledName << '\n'; - os << Indent << "Reference Count: " << m_ReferenceCount.load() << '\n'; + os << Indent << "Reference Count: " << m_ReferenceCount.loadRelaxed() << '\n'; return os; } /** * Define a default print header for all objects. */ QDebug Object::PrintHeader(QDebug os, Indent Indent) const { os << Indent << this->GetClassName() << " (" << this << ")\n"; return os; } /** * Define a default print trailer for all objects. */ QDebug Object::PrintTrailer(QDebug os, Indent /*Indent*/) const { return os; } // ============== Indent related implementations ============== static const char blanks[41] = " "; Indent Indent::GetNextIndent() { int Indent = m_Indent + 2; if (Indent > 40) { Indent = 40; } return Indent; } QDebug operator<<(QDebug os, const berry::Indent& ind) { os.nospace() << blanks + (40 - ind.m_Indent); return os; } } // namespace berry QDebug operator<<(QDebug os, const berry::Object& o) { return o.Print(os); } QDebug operator<<(QDebug os, const berry::SmartPointer& o) { return o->Print(os); } QDebug operator<<(QDebug os, const berry::SmartPointer& o) { return o->Print(os); } QTextStream& operator<<(QTextStream& os, const berry::Object& o) { os << o.ToString(); return os; } QTextStream& operator<<(QTextStream& os, const berry::SmartPointer& o) { os << o->ToString(); return os; } //QTextStream& operator<<(QTextStream& os, const berry::SmartPointer& o) //{ // os << o->ToString(); // return os; //} uint qHash(const berry::Object& o) { return o.HashCode(); } diff --git a/Plugins/org.blueberry.core.runtime/src/berryObject.h b/Plugins/org.blueberry.core.runtime/src/berryObject.h index 513786dcd5..785919ee61 100644 --- a/Plugins/org.blueberry.core.runtime/src/berryObject.h +++ b/Plugins/org.blueberry.core.runtime/src/berryObject.h @@ -1,241 +1,241 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef BERRYOBJECT_H_ #define BERRYOBJECT_H_ #include #include "berryMacros.h" #include "berryMessage.h" #include #include #include #include #include #ifdef _MSC_VER // disable inheritance by dominance warnings #pragma warning( disable : 4250 4275 ) #endif class QDebug; class QTextStream; namespace berry { class org_blueberry_core_runtime_EXPORT Indent { public: /** Standard class typedefs. */ typedef Indent Self; /** Construct the object with an initial Indentation level. */ Indent(int ind = 0) { m_Indent=ind; } /** * Determine the next Indentation level. Keep Indenting by two until the * a maximum of forty spaces is reached. */ Indent GetNextIndent(); /** Print out the Indentation. Basically output a bunch of spaces. */ friend org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const Indent& o); private: int m_Indent; }; /** \class Object * \brief Light weight base class for most BlueBerry classes. * * Object is copied from itk::LightObject and is the highest * level base class for most BlueBerry objects. It * implements reference counting and the API for object printing. * */ class org_blueberry_core_runtime_EXPORT Object { private: mutable Message<> m_DestroyMessage; public: typedef Object Self; typedef berry::SmartPointer Pointer; typedef berry::SmartPointer ConstPointer; typedef berry::WeakPointer WeakPtr; typedef berry::WeakPointer ConstWeakPtr; static const char* GetStaticClassName(); virtual QString GetClassName() const; static Reflection::TypeInfo GetStaticTypeInfo(); virtual Reflection::TypeInfo GetTypeInfo() const; static QList GetStaticSuperclasses(); virtual QList GetSuperclasses() const; /** Delete an BlueBerry object. This method should always be used to delete an * object when the new operator was used to create it. Using the C * delete method will not work with reference counting. */ virtual void Delete(); #ifdef _WIN32 /** Used to avoid dll boundary problems. */ void* operator new(size_t); void* operator new[](size_t); void operator delete(void*); void operator delete[](void*, size_t); #endif /** * Cause the object to print itself out. This is usually used to provide * detailed information about the object's state. It just calls the * header/self/trailer virtual print methods, which can be overridden by * subclasses. */ QDebug Print(QDebug os, Indent Indent=0) const; /** * Returns a string representation of this object. The default * implementation returns an empty string. */ virtual QString ToString() const; /** * Returns a hash code value for the object. */ virtual uint HashCode() const; /** * Override this method to implement a specific "less than" operator * for associative STL containers. */ virtual bool operator<(const Object*) const; /** Increase the reference count (mark as used by another object). */ void Register() const; /** Decrease the reference count (release by another object). * Set del to false if you do not want the object to be deleted if * the reference count is zero (use with care!) */ void UnRegister(bool del = true) const; /** Gets the reference count on this object. */ int GetReferenceCount() const { - return m_ReferenceCount.load(); + return m_ReferenceCount.loadRelaxed(); } /** Sets the reference count on this object. This is a dangerous * method, use it with care. */ void SetReferenceCount(int); inline void AddDestroyListener(const MessageAbstractDelegate<>& delegate) const { m_DestroyMessage += delegate; } inline void RemoveDestroyListener(const MessageAbstractDelegate<>& delegate) const { m_DestroyMessage -= delegate; } /** * A generic comparison method. Override this method in subclasses and * cast to your derived class to provide a more detailed comparison. */ virtual bool operator==(const Object*) const; #ifdef BLUEBERRY_DEBUG_SMARTPOINTER unsigned int GetTraceId() const; private: unsigned int m_TraceId; unsigned int& GetTraceIdCounter() const; public: #endif protected: friend struct QScopedPointerObjectDeleter; Object(); virtual ~Object(); /** * Methods invoked by Print() to print information about the object * including superclasses. Typically not called by the user (use Print() * instead) but used in the hierarchical print process to combine the * output of several classes. */ virtual QDebug PrintSelf(QDebug os, Indent indent) const; virtual QDebug PrintHeader(QDebug os, Indent indent) const; virtual QDebug PrintTrailer(QDebug os, Indent indent) const; /** Number of uses of this object by other objects. */ mutable QAtomicInt m_ReferenceCount; /** Mutex lock to protect modification to the reference count */ mutable QMutex m_ReferenceCountLock; private: Object(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented }; // A custom deleter for QScopedPointer // berry::Object instances in a QScopedPointer should have reference count one, // such that they are not accidentally deleted when a temporary smart pointer // pointing to it goes out of scope. This deleter fixes the reference count and // always deletes the instance. Use a berry::SmartPointer if the lifetime should // exceed the one of the pointer. struct QScopedPointerObjectDeleter { static inline void cleanup(Object* obj) { if (obj == nullptr) return; obj->UnRegister(false); delete obj; } }; org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const berry::Indent& o); } /** * This operator allows all subclasses of Object to be printed via QDebug <<. * It in turn invokes the Print method, which in turn will invoke the * PrintSelf method that all objects should define, if they have anything * interesting to print out. */ org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const berry::Object& o); org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const berry::SmartPointer& o); org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const berry::SmartPointer& o); org_blueberry_core_runtime_EXPORT QTextStream& operator<<(QTextStream& os, const berry::Object& o); org_blueberry_core_runtime_EXPORT QTextStream& operator<<(QTextStream& os, const berry::SmartPointer& o); //org_blueberry_core_runtime_EXPORT QTextStream& operator<<(QTextStream& os, const berry::SmartPointer& o); Q_DECLARE_METATYPE(berry::Object::Pointer) org_blueberry_core_runtime_EXPORT uint qHash(const berry::Object& o); #endif /*BERRYOBJECT_H_*/