1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 #if ! defined(OSL_DIAGNOSE_HXX_INCLUDED) 28 #define OSL_DIAGNOSE_HXX_INCLUDED 29 30 #if ! defined(_OSL_DIAGNOSE_H_) 31 #include "osl/diagnose.h" 32 #endif 33 #if ! defined(_OSL_INTERLOCK_H_) 34 #include "osl/interlck.h" 35 #endif 36 #if ! defined(_OSL_MUTEX_HXX_) 37 #include "osl/mutex.hxx" 38 #endif 39 #if ! defined(INCLUDED_RTL_ALLOCATOR_HXX) 40 #include "rtl/allocator.hxx" 41 #endif 42 #if ! defined(_RTL_INSTANCE_HXX_) 43 #include "rtl/instance.hxx" 44 #endif 45 #include <hash_set> 46 #include <functional> 47 #include <typeinfo> 48 49 namespace osl { 50 /// @internal 51 namespace detail { 52 53 struct ObjectRegistryData; 54 55 } // namespace detail 56 } // namespace osl 57 58 extern "C" { 59 60 /** @internal */ 61 bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses( char const* pName ) 62 SAL_THROW_EXTERN_C(); 63 64 /** @internal */ 65 bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount( 66 ::osl::detail::ObjectRegistryData const& rData, ::std::size_t nExpected ) 67 SAL_THROW_EXTERN_C(); 68 69 /** @internal */ 70 void SAL_CALL osl_detail_ObjectRegistry_registerObject( 71 ::osl::detail::ObjectRegistryData & rData, void const* pObj ) 72 SAL_THROW_EXTERN_C(); 73 74 /** @internal */ 75 void SAL_CALL osl_detail_ObjectRegistry_revokeObject( 76 ::osl::detail::ObjectRegistryData & rData, void const* pObj ) 77 SAL_THROW_EXTERN_C(); 78 79 /** @internal */ 80 ::osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex() 81 SAL_THROW_EXTERN_C(); 82 83 } // extern "C" 84 85 namespace osl { 86 87 /// @internal 88 namespace detail { 89 90 struct VoidPtrHash : ::std::unary_function<void const*, ::std::size_t> { 91 ::std::size_t operator()( void const* p ) const { 92 ::std::size_t const d = static_cast< ::std::size_t >( 93 reinterpret_cast< ::std::ptrdiff_t >(p) ); 94 return d + (d >> 3); 95 } 96 }; 97 98 typedef ::std::hash_set<void const*, VoidPtrHash, ::std::equal_to<void const*>, 99 ::rtl::Allocator<void const*> > VoidPointerSet; 100 101 struct ObjectRegistryData { 102 ObjectRegistryData( ::std::type_info const& rTypeInfo ) 103 : m_pName(rTypeInfo.name()), m_nCount(0), m_addresses(), 104 m_bStoreAddresses(osl_detail_ObjectRegistry_storeAddresses(m_pName)){} 105 106 char const* const m_pName; 107 oslInterlockedCount m_nCount; 108 VoidPointerSet m_addresses; 109 bool const m_bStoreAddresses; 110 }; 111 112 template <typename T> 113 class ObjectRegistry 114 { 115 public: 116 ObjectRegistry() : m_data( typeid(T) ) {} 117 ~ObjectRegistry() { checkObjectCount(0); } 118 119 bool checkObjectCount( ::std::size_t nExpected ) const { 120 bool const bRet = osl_detail_ObjectRegistry_checkObjectCount( 121 m_data, nExpected ); 122 if (!bRet && m_data.m_bStoreAddresses) { 123 MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() ); 124 // following loop is for debugging purposes, iterating over map: 125 VoidPointerSet::const_iterator iPos(m_data.m_addresses.begin()); 126 VoidPointerSet::const_iterator const iEnd(m_data.m_addresses.end()); 127 for ( ; iPos != iEnd; ++iPos ) { 128 OSL_ASSERT( *iPos != 0 ); 129 } 130 } 131 return bRet; 132 } 133 134 void registerObject( void const* pObj ) { 135 osl_detail_ObjectRegistry_registerObject(m_data, pObj); 136 } 137 138 void revokeObject( void const* pObj ) { 139 osl_detail_ObjectRegistry_revokeObject(m_data, pObj); 140 } 141 142 private: 143 // not impl: 144 ObjectRegistry( ObjectRegistry const& ); 145 ObjectRegistry const& operator=( ObjectRegistry const& ); 146 147 ObjectRegistryData m_data; 148 }; 149 150 } // namespace detail 151 152 /** Helper class which indicates leaking object(s) of a particular class in 153 non-pro builds; use e.g. 154 155 <pre> 156 class MyClass : private osl::DebugBase<MyClass> {...}; 157 </pre> 158 159 Using the environment variable 160 161 OSL_DEBUGBASE_STORE_ADDRESSES=MyClass;YourClass;... 162 163 you can specify a ';'-separated list of strings matching to class names 164 (or "all" for all classes), for which DebugBase stores addresses to created 165 objects instead of just counting them. This enables you to iterate over 166 leaking objects in your debugger. 167 168 @tpl InheritingClassT binds the template instance to that class 169 @internal Use at own risk. 170 For now this is just public (yet unpublished) API and may change 171 in the future! 172 */ 173 template <typename InheritingClassT> 174 class DebugBase 175 { 176 public: 177 #if OSL_DEBUG_LEVEL <= 0 178 static bool checkObjectCount( ::std::size_t = 0 ) { return true; } 179 #else // OSL_DEBUG_LEVEL > 0 180 /** @return whether the expected number of objects is alive, 181 else this function OSL_ASSERTs 182 */ 183 static bool checkObjectCount( ::std::size_t nExpected = 0 ) { 184 return StaticObjectRegistry::get().checkObjectCount(nExpected); 185 } 186 187 protected: 188 DebugBase() { 189 StaticObjectRegistry::get().registerObject( this ); 190 } 191 ~DebugBase() { 192 StaticObjectRegistry::get().revokeObject( this ); 193 } 194 195 private: 196 struct StaticObjectRegistry 197 : ::rtl::Static<detail::ObjectRegistry<InheritingClassT>, 198 StaticObjectRegistry> {}; 199 #endif 200 }; 201 202 } // namespace osl 203 204 #endif // ! defined(OSL_DIAGNOSE_HXX_INCLUDED) 205 206