bump product version to 4.2.0.1
[LibreOffice.git] / include / osl / diagnose.hxx
blob5ae21d742cef966b71427e63ed14c1f51fea0a1d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #ifndef INCLUDED_OSL_DIAGNOSE_HXX
20 #define INCLUDED_OSL_DIAGNOSE_HXX
22 #include <sal/config.h>
24 #include <functional>
25 #include <typeinfo>
27 #include <config_global.h>
29 #if !HAVE_CXX11
30 #define BOOST_NO_0X_HDR_TYPEINDEX
31 #endif
32 #include <boost/unordered_set.hpp>
33 #include <osl/diagnose.h>
34 #include <osl/interlck.h>
35 #include <osl/mutex.hxx>
36 #include <rtl/allocator.hxx>
37 #include <rtl/instance.hxx>
38 #include <sal/log.hxx>
39 #include <sal/saldllapi.h>
40 #include <sal/types.h>
42 /// @cond INTERNAL
44 namespace osl {
45 namespace detail {
47 struct ObjectRegistryData;
49 } // namespace detail
50 } // namespace osl
52 extern "C" {
54 SAL_DLLPUBLIC bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses(
55 char const* pName )
56 SAL_THROW_EXTERN_C();
58 SAL_DLLPUBLIC bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount(
59 ::osl::detail::ObjectRegistryData const& rData, ::std::size_t nExpected )
60 SAL_THROW_EXTERN_C();
62 SAL_DLLPUBLIC void SAL_CALL osl_detail_ObjectRegistry_registerObject(
63 ::osl::detail::ObjectRegistryData & rData, void const* pObj )
64 SAL_THROW_EXTERN_C();
66 SAL_DLLPUBLIC void SAL_CALL osl_detail_ObjectRegistry_revokeObject(
67 ::osl::detail::ObjectRegistryData & rData, void const* pObj )
68 SAL_THROW_EXTERN_C();
70 // These functions presumably should not be extern "C", but changing
71 // that would break binary compatibility.
72 #ifdef __clang__
73 #pragma clang diagnostic push
74 // Guard against slightly older clang versions that don't have
75 // -Wreturn-type-c-linkage...
76 #pragma clang diagnostic ignored "-Wunknown-pragmas"
77 #pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
78 #endif
80 SAL_DLLPUBLIC ::osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex()
81 SAL_THROW_EXTERN_C();
83 #ifdef __clang__
84 #pragma clang diagnostic pop
85 #endif
87 } // extern "C"
89 namespace osl {
91 namespace detail {
93 struct VoidPtrHash : ::std::unary_function<void const*, ::std::size_t> {
94 ::std::size_t operator()( void const* p ) const {
95 ::std::size_t const d = static_cast< ::std::size_t >(
96 reinterpret_cast< ::std::ptrdiff_t >(p) );
97 return d + (d >> 3);
101 typedef ::boost::unordered_set<void const*, VoidPtrHash, ::std::equal_to<void const*>,
102 ::rtl::Allocator<void const*> > VoidPointerSet;
104 struct ObjectRegistryData {
105 ObjectRegistryData( ::std::type_info const& rTypeInfo )
106 : m_pName(rTypeInfo.name()), m_nCount(0), m_addresses(),
107 m_bStoreAddresses(osl_detail_ObjectRegistry_storeAddresses(m_pName)){}
109 char const* const m_pName;
110 oslInterlockedCount m_nCount;
111 VoidPointerSet m_addresses;
112 bool const m_bStoreAddresses;
115 template <typename T>
116 class ObjectRegistry
118 public:
119 ObjectRegistry() : m_data( typeid(T) ) {}
120 ~ObjectRegistry() { checkObjectCount(0); }
122 bool checkObjectCount( ::std::size_t nExpected ) const {
123 bool const bRet = osl_detail_ObjectRegistry_checkObjectCount(
124 m_data, nExpected );
125 if (!bRet && m_data.m_bStoreAddresses) {
126 MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
127 // following loop is for debugging purposes, iterating over map:
128 VoidPointerSet::const_iterator iPos(m_data.m_addresses.begin());
129 VoidPointerSet::const_iterator const iEnd(m_data.m_addresses.end());
130 for ( ; iPos != iEnd; ++iPos ) {
131 SAL_WARN_IF( *iPos == 0, "sal.debug", "null pointer" );
134 return bRet;
137 void registerObject( void const* pObj ) {
138 osl_detail_ObjectRegistry_registerObject(m_data, pObj);
141 void revokeObject( void const* pObj ) {
142 osl_detail_ObjectRegistry_revokeObject(m_data, pObj);
145 private:
146 // not impl:
147 ObjectRegistry( ObjectRegistry const& );
148 ObjectRegistry const& operator=( ObjectRegistry const& );
150 ObjectRegistryData m_data;
153 } // namespace detail
155 /** Helper class which indicates leaking object(s) of a particular class in
156 non-pro builds; use e.g.
158 <pre>
159 class MyClass : private osl::DebugBase<MyClass> {...};
160 </pre>
162 Using the environment variable
164 OSL_DEBUGBASE_STORE_ADDRESSES=MyClass;YourClass;...
166 you can specify a ';'-separated list of strings matching to class names
167 (or "all" for all classes), for which DebugBase stores addresses to created
168 objects instead of just counting them. This enables you to iterate over
169 leaking objects in your debugger.
171 @tparam InheritingClassT binds the template instance to that class
172 @attention Use at own risk.
173 For now this is just public (yet unpublished) API and may change
174 in the future!
176 template <typename InheritingClassT>
177 class DebugBase
179 public:
180 #if OSL_DEBUG_LEVEL <= 0
181 static bool checkObjectCount( ::std::size_t = 0 ) { return true; }
182 #else // OSL_DEBUG_LEVEL > 0
183 /** @return whether the expected number of objects is alive,
184 else this function SAL_WARNs
186 static bool checkObjectCount( ::std::size_t nExpected = 0 ) {
187 return StaticObjectRegistry::get().checkObjectCount(nExpected);
190 protected:
191 DebugBase() {
192 StaticObjectRegistry::get().registerObject( this );
194 ~DebugBase() {
195 StaticObjectRegistry::get().revokeObject( this );
198 private:
199 struct StaticObjectRegistry
200 : ::rtl::Static<detail::ObjectRegistry<InheritingClassT>,
201 StaticObjectRegistry> {};
202 #endif
205 } // namespace osl
207 /// @endcond
209 #endif // ! defined( INCLUDED_OSL_DIAGNOSE_HXX)
211 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */