xref: /aoo42x/main/sal/inc/osl/diagnose.hxx (revision 565d668c)
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