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