1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 OSL_DIAGNOSE_HXX_INCLUDED
20 #define OSL_DIAGNOSE_HXX_INCLUDED
22 #include "sal/config.h"
28 #define BOOST_NO_0X_HDR_TYPEINDEX
30 #include "boost/unordered_set.hpp"
31 #include "osl/diagnose.h"
32 #include "osl/interlck.h"
33 #include "osl/mutex.hxx"
34 #include "rtl/allocator.hxx"
35 #include "rtl/instance.hxx"
36 #include "sal/log.hxx"
37 #include "sal/saldllapi.h"
38 #include "sal/types.h"
45 struct ObjectRegistryData
;
52 SAL_DLLPUBLIC
bool SAL_CALL
osl_detail_ObjectRegistry_storeAddresses(
56 SAL_DLLPUBLIC
bool SAL_CALL
osl_detail_ObjectRegistry_checkObjectCount(
57 ::osl::detail::ObjectRegistryData
const& rData
, ::std::size_t nExpected
)
60 SAL_DLLPUBLIC
void SAL_CALL
osl_detail_ObjectRegistry_registerObject(
61 ::osl::detail::ObjectRegistryData
& rData
, void const* pObj
)
64 SAL_DLLPUBLIC
void SAL_CALL
osl_detail_ObjectRegistry_revokeObject(
65 ::osl::detail::ObjectRegistryData
& rData
, void const* pObj
)
68 // These functions presumably should not be extern "C", but changing
69 // that would break binary compatibility.
71 #pragma clang diagnostic push
72 // Guard against slightly older clang versions that don't have
73 // -Wreturn-type-c-linkage...
74 #pragma clang diagnostic ignored "-Wunknown-pragmas"
75 #pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
78 SAL_DLLPUBLIC ::osl::Mutex
& SAL_CALL
osl_detail_ObjectRegistry_getMutex()
82 #pragma clang diagnostic pop
91 struct VoidPtrHash
: ::std::unary_function
<void const*, ::std::size_t> {
92 ::std::size_t operator()( void const* p
) const {
93 ::std::size_t const d
= static_cast< ::std::size_t >(
94 reinterpret_cast< ::std::ptrdiff_t >(p
) );
99 typedef ::boost::unordered_set
<void const*, VoidPtrHash
, ::std::equal_to
<void const*>,
100 ::rtl::Allocator
<void const*> > VoidPointerSet
;
102 struct ObjectRegistryData
{
103 ObjectRegistryData( ::std::type_info
const& rTypeInfo
)
104 : m_pName(rTypeInfo
.name()), m_nCount(0), m_addresses(),
105 m_bStoreAddresses(osl_detail_ObjectRegistry_storeAddresses(m_pName
)){}
107 char const* const m_pName
;
108 oslInterlockedCount m_nCount
;
109 VoidPointerSet m_addresses
;
110 bool const m_bStoreAddresses
;
113 template <typename T
>
117 ObjectRegistry() : m_data( typeid(T
) ) {}
118 ~ObjectRegistry() { checkObjectCount(0); }
120 bool checkObjectCount( ::std::size_t nExpected
) const {
121 bool const bRet
= osl_detail_ObjectRegistry_checkObjectCount(
123 if (!bRet
&& m_data
.m_bStoreAddresses
) {
124 MutexGuard
const guard( osl_detail_ObjectRegistry_getMutex() );
125 // following loop is for debugging purposes, iterating over map:
126 VoidPointerSet::const_iterator
iPos(m_data
.m_addresses
.begin());
127 VoidPointerSet::const_iterator
const iEnd(m_data
.m_addresses
.end());
128 for ( ; iPos
!= iEnd
; ++iPos
) {
129 SAL_WARN_IF( *iPos
== 0, "sal.debug", "null pointer" );
135 void registerObject( void const* pObj
) {
136 osl_detail_ObjectRegistry_registerObject(m_data
, pObj
);
139 void revokeObject( void const* pObj
) {
140 osl_detail_ObjectRegistry_revokeObject(m_data
, pObj
);
145 ObjectRegistry( ObjectRegistry
const& );
146 ObjectRegistry
const& operator=( ObjectRegistry
const& );
148 ObjectRegistryData m_data
;
151 } // namespace detail
153 /** Helper class which indicates leaking object(s) of a particular class in
154 non-pro builds; use e.g.
157 class MyClass : private osl::DebugBase<MyClass> {...};
160 Using the environment variable
162 OSL_DEBUGBASE_STORE_ADDRESSES=MyClass;YourClass;...
164 you can specify a ';'-separated list of strings matching to class names
165 (or "all" for all classes), for which DebugBase stores addresses to created
166 objects instead of just counting them. This enables you to iterate over
167 leaking objects in your debugger.
169 @tparam InheritingClassT binds the template instance to that class
170 @attention Use at own risk.
171 For now this is just public (yet unpublished) API and may change
174 template <typename InheritingClassT
>
178 #if OSL_DEBUG_LEVEL <= 0
179 static bool checkObjectCount( ::std::size_t = 0 ) { return true; }
180 #else // OSL_DEBUG_LEVEL > 0
181 /** @return whether the expected number of objects is alive,
182 else this function SAL_WARNs
184 static bool checkObjectCount( ::std::size_t nExpected
= 0 ) {
185 return StaticObjectRegistry::get().checkObjectCount(nExpected
);
190 StaticObjectRegistry::get().registerObject( this );
193 StaticObjectRegistry::get().revokeObject( this );
197 struct StaticObjectRegistry
198 : ::rtl::Static
<detail::ObjectRegistry
<InheritingClassT
>,
199 StaticObjectRegistry
> {};
207 #endif // ! defined(OSL_DIAGNOSE_HXX_INCLUDED)
209 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */