1*565d668cSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*565d668cSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*565d668cSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*565d668cSAndrew Rist * distributed with this work for additional information 6*565d668cSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*565d668cSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*565d668cSAndrew Rist * "License"); you may not use this file except in compliance 9*565d668cSAndrew Rist * with the License. You may obtain a copy of the License at 10*565d668cSAndrew Rist * 11*565d668cSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*565d668cSAndrew Rist * 13*565d668cSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*565d668cSAndrew Rist * software distributed under the License is distributed on an 15*565d668cSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*565d668cSAndrew Rist * KIND, either express or implied. See the License for the 17*565d668cSAndrew Rist * specific language governing permissions and limitations 18*565d668cSAndrew Rist * under the License. 19*565d668cSAndrew Rist * 20*565d668cSAndrew Rist *************************************************************/ 21*565d668cSAndrew Rist 22*565d668cSAndrew Rist 23cdf0e10cSrcweir #if ! defined(OSL_DIAGNOSE_HXX_INCLUDED) 24cdf0e10cSrcweir #define OSL_DIAGNOSE_HXX_INCLUDED 25cdf0e10cSrcweir 26cdf0e10cSrcweir #if ! defined(_OSL_DIAGNOSE_H_) 27cdf0e10cSrcweir #include "osl/diagnose.h" 28cdf0e10cSrcweir #endif 29cdf0e10cSrcweir #if ! defined(_OSL_INTERLOCK_H_) 30cdf0e10cSrcweir #include "osl/interlck.h" 31cdf0e10cSrcweir #endif 32cdf0e10cSrcweir #if ! defined(_OSL_MUTEX_HXX_) 33cdf0e10cSrcweir #include "osl/mutex.hxx" 34cdf0e10cSrcweir #endif 35cdf0e10cSrcweir #if ! defined(INCLUDED_RTL_ALLOCATOR_HXX) 36cdf0e10cSrcweir #include "rtl/allocator.hxx" 37cdf0e10cSrcweir #endif 38cdf0e10cSrcweir #if ! defined(_RTL_INSTANCE_HXX_) 39cdf0e10cSrcweir #include "rtl/instance.hxx" 40cdf0e10cSrcweir #endif 41cdf0e10cSrcweir #include <hash_set> 42cdf0e10cSrcweir #include <functional> 43cdf0e10cSrcweir #include <typeinfo> 44cdf0e10cSrcweir 45cdf0e10cSrcweir namespace osl { 46cdf0e10cSrcweir /// @internal 47cdf0e10cSrcweir namespace detail { 48cdf0e10cSrcweir 49cdf0e10cSrcweir struct ObjectRegistryData; 50cdf0e10cSrcweir 51cdf0e10cSrcweir } // namespace detail 52cdf0e10cSrcweir } // namespace osl 53cdf0e10cSrcweir 54cdf0e10cSrcweir extern "C" { 55cdf0e10cSrcweir 56cdf0e10cSrcweir /** @internal */ 57cdf0e10cSrcweir bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses( char const* pName ) 58cdf0e10cSrcweir SAL_THROW_EXTERN_C(); 59cdf0e10cSrcweir 60cdf0e10cSrcweir /** @internal */ 61cdf0e10cSrcweir bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount( 62cdf0e10cSrcweir ::osl::detail::ObjectRegistryData const& rData, ::std::size_t nExpected ) 63cdf0e10cSrcweir SAL_THROW_EXTERN_C(); 64cdf0e10cSrcweir 65cdf0e10cSrcweir /** @internal */ 66cdf0e10cSrcweir void SAL_CALL osl_detail_ObjectRegistry_registerObject( 67cdf0e10cSrcweir ::osl::detail::ObjectRegistryData & rData, void const* pObj ) 68cdf0e10cSrcweir SAL_THROW_EXTERN_C(); 69cdf0e10cSrcweir 70cdf0e10cSrcweir /** @internal */ 71cdf0e10cSrcweir void SAL_CALL osl_detail_ObjectRegistry_revokeObject( 72cdf0e10cSrcweir ::osl::detail::ObjectRegistryData & rData, void const* pObj ) 73cdf0e10cSrcweir SAL_THROW_EXTERN_C(); 74cdf0e10cSrcweir 75cdf0e10cSrcweir /** @internal */ 76cdf0e10cSrcweir ::osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex() 77cdf0e10cSrcweir SAL_THROW_EXTERN_C(); 78cdf0e10cSrcweir 79cdf0e10cSrcweir } // extern "C" 80cdf0e10cSrcweir 81cdf0e10cSrcweir namespace osl { 82cdf0e10cSrcweir 83cdf0e10cSrcweir /// @internal 84cdf0e10cSrcweir namespace detail { 85cdf0e10cSrcweir 86cdf0e10cSrcweir struct VoidPtrHash : ::std::unary_function<void const*, ::std::size_t> { 87cdf0e10cSrcweir ::std::size_t operator()( void const* p ) const { 88cdf0e10cSrcweir ::std::size_t const d = static_cast< ::std::size_t >( 89cdf0e10cSrcweir reinterpret_cast< ::std::ptrdiff_t >(p) ); 90cdf0e10cSrcweir return d + (d >> 3); 91cdf0e10cSrcweir } 92cdf0e10cSrcweir }; 93cdf0e10cSrcweir 94cdf0e10cSrcweir typedef ::std::hash_set<void const*, VoidPtrHash, ::std::equal_to<void const*>, 95cdf0e10cSrcweir ::rtl::Allocator<void const*> > VoidPointerSet; 96cdf0e10cSrcweir 97cdf0e10cSrcweir struct ObjectRegistryData { 98cdf0e10cSrcweir ObjectRegistryData( ::std::type_info const& rTypeInfo ) 99cdf0e10cSrcweir : m_pName(rTypeInfo.name()), m_nCount(0), m_addresses(), 100cdf0e10cSrcweir m_bStoreAddresses(osl_detail_ObjectRegistry_storeAddresses(m_pName)){} 101cdf0e10cSrcweir 102cdf0e10cSrcweir char const* const m_pName; 103cdf0e10cSrcweir oslInterlockedCount m_nCount; 104cdf0e10cSrcweir VoidPointerSet m_addresses; 105cdf0e10cSrcweir bool const m_bStoreAddresses; 106cdf0e10cSrcweir }; 107cdf0e10cSrcweir 108cdf0e10cSrcweir template <typename T> 109cdf0e10cSrcweir class ObjectRegistry 110cdf0e10cSrcweir { 111cdf0e10cSrcweir public: 112cdf0e10cSrcweir ObjectRegistry() : m_data( typeid(T) ) {} 113cdf0e10cSrcweir ~ObjectRegistry() { checkObjectCount(0); } 114cdf0e10cSrcweir 115cdf0e10cSrcweir bool checkObjectCount( ::std::size_t nExpected ) const { 116cdf0e10cSrcweir bool const bRet = osl_detail_ObjectRegistry_checkObjectCount( 117cdf0e10cSrcweir m_data, nExpected ); 118cdf0e10cSrcweir if (!bRet && m_data.m_bStoreAddresses) { 119cdf0e10cSrcweir MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() ); 120cdf0e10cSrcweir // following loop is for debugging purposes, iterating over map: 121cdf0e10cSrcweir VoidPointerSet::const_iterator iPos(m_data.m_addresses.begin()); 122cdf0e10cSrcweir VoidPointerSet::const_iterator const iEnd(m_data.m_addresses.end()); 123cdf0e10cSrcweir for ( ; iPos != iEnd; ++iPos ) { 124cdf0e10cSrcweir OSL_ASSERT( *iPos != 0 ); 125cdf0e10cSrcweir } 126cdf0e10cSrcweir } 127cdf0e10cSrcweir return bRet; 128cdf0e10cSrcweir } 129cdf0e10cSrcweir 130cdf0e10cSrcweir void registerObject( void const* pObj ) { 131cdf0e10cSrcweir osl_detail_ObjectRegistry_registerObject(m_data, pObj); 132cdf0e10cSrcweir } 133cdf0e10cSrcweir 134cdf0e10cSrcweir void revokeObject( void const* pObj ) { 135cdf0e10cSrcweir osl_detail_ObjectRegistry_revokeObject(m_data, pObj); 136cdf0e10cSrcweir } 137cdf0e10cSrcweir 138cdf0e10cSrcweir private: 139cdf0e10cSrcweir // not impl: 140cdf0e10cSrcweir ObjectRegistry( ObjectRegistry const& ); 141cdf0e10cSrcweir ObjectRegistry const& operator=( ObjectRegistry const& ); 142cdf0e10cSrcweir 143cdf0e10cSrcweir ObjectRegistryData m_data; 144cdf0e10cSrcweir }; 145cdf0e10cSrcweir 146cdf0e10cSrcweir } // namespace detail 147cdf0e10cSrcweir 148cdf0e10cSrcweir /** Helper class which indicates leaking object(s) of a particular class in 149cdf0e10cSrcweir non-pro builds; use e.g. 150cdf0e10cSrcweir 151cdf0e10cSrcweir <pre> 152cdf0e10cSrcweir class MyClass : private osl::DebugBase<MyClass> {...}; 153cdf0e10cSrcweir </pre> 154cdf0e10cSrcweir 155cdf0e10cSrcweir Using the environment variable 156cdf0e10cSrcweir 157cdf0e10cSrcweir OSL_DEBUGBASE_STORE_ADDRESSES=MyClass;YourClass;... 158cdf0e10cSrcweir 159cdf0e10cSrcweir you can specify a ';'-separated list of strings matching to class names 160cdf0e10cSrcweir (or "all" for all classes), for which DebugBase stores addresses to created 161cdf0e10cSrcweir objects instead of just counting them. This enables you to iterate over 162cdf0e10cSrcweir leaking objects in your debugger. 163cdf0e10cSrcweir 164cdf0e10cSrcweir @tpl InheritingClassT binds the template instance to that class 165cdf0e10cSrcweir @internal Use at own risk. 166cdf0e10cSrcweir For now this is just public (yet unpublished) API and may change 167cdf0e10cSrcweir in the future! 168cdf0e10cSrcweir */ 169cdf0e10cSrcweir template <typename InheritingClassT> 170cdf0e10cSrcweir class DebugBase 171cdf0e10cSrcweir { 172cdf0e10cSrcweir public: 173cdf0e10cSrcweir #if OSL_DEBUG_LEVEL <= 0 174cdf0e10cSrcweir static bool checkObjectCount( ::std::size_t = 0 ) { return true; } 175cdf0e10cSrcweir #else // OSL_DEBUG_LEVEL > 0 176cdf0e10cSrcweir /** @return whether the expected number of objects is alive, 177cdf0e10cSrcweir else this function OSL_ASSERTs 178cdf0e10cSrcweir */ 179cdf0e10cSrcweir static bool checkObjectCount( ::std::size_t nExpected = 0 ) { 180cdf0e10cSrcweir return StaticObjectRegistry::get().checkObjectCount(nExpected); 181cdf0e10cSrcweir } 182cdf0e10cSrcweir 183cdf0e10cSrcweir protected: 184cdf0e10cSrcweir DebugBase() { 185cdf0e10cSrcweir StaticObjectRegistry::get().registerObject( this ); 186cdf0e10cSrcweir } 187cdf0e10cSrcweir ~DebugBase() { 188cdf0e10cSrcweir StaticObjectRegistry::get().revokeObject( this ); 189cdf0e10cSrcweir } 190cdf0e10cSrcweir 191cdf0e10cSrcweir private: 192cdf0e10cSrcweir struct StaticObjectRegistry 193cdf0e10cSrcweir : ::rtl::Static<detail::ObjectRegistry<InheritingClassT>, 194cdf0e10cSrcweir StaticObjectRegistry> {}; 195cdf0e10cSrcweir #endif 196cdf0e10cSrcweir }; 197cdf0e10cSrcweir 198cdf0e10cSrcweir } // namespace osl 199cdf0e10cSrcweir 200cdf0e10cSrcweir #endif // ! defined(OSL_DIAGNOSE_HXX_INCLUDED) 201cdf0e10cSrcweir 202