Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / include / osl / diagnose.hxx
blobc515eaf54827d51348f36e75e7a769a12c76eeb1
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 /// @cond INTERNAL
24 #include <sal/config.h>
26 #include <cstddef>
27 #include <functional>
28 #include <typeinfo>
29 #include <unordered_set>
31 #include <osl/diagnose.h>
32 #include <osl/interlck.h>
33 #include <osl/mutex.hxx>
34 #include <rtl/instance.hxx>
35 #include <sal/log.hxx>
36 #include <sal/saldllapi.h>
37 #include <sal/types.h>
39 namespace osl {
40 namespace detail {
42 struct ObjectRegistryData;
44 } // namespace detail
45 } // namespace osl
47 extern "C" {
49 SAL_DLLPUBLIC bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses(
50 char const* pName )
51 SAL_THROW_EXTERN_C();
53 SAL_DLLPUBLIC bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount(
54 ::osl::detail::ObjectRegistryData const& rData, ::std::size_t nExpected )
55 SAL_THROW_EXTERN_C();
57 SAL_DLLPUBLIC void SAL_CALL osl_detail_ObjectRegistry_registerObject(
58 ::osl::detail::ObjectRegistryData & rData, void const* pObj )
59 SAL_THROW_EXTERN_C();
61 SAL_DLLPUBLIC void SAL_CALL osl_detail_ObjectRegistry_revokeObject(
62 ::osl::detail::ObjectRegistryData & rData, void const* pObj )
63 SAL_THROW_EXTERN_C();
65 // These functions presumably should not be extern "C", but changing
66 // that would break binary compatibility.
67 #ifdef __clang__
68 #pragma clang diagnostic push
69 // Guard against slightly older clang versions that don't have
70 // -Wreturn-type-c-linkage...
71 #pragma clang diagnostic ignored "-Wunknown-pragmas"
72 #pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
73 #endif
75 SAL_DLLPUBLIC ::osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex()
76 SAL_THROW_EXTERN_C();
78 #ifdef __clang__
79 #pragma clang diagnostic pop
80 #endif
82 } // extern "C"
84 namespace osl {
86 namespace detail {
88 struct VoidPtrHash : ::std::unary_function<void const*, ::std::size_t> {
89 ::std::size_t operator()( void const* p ) const {
90 ::std::size_t const d = static_cast< ::std::size_t >(
91 reinterpret_cast< ::std::ptrdiff_t >(p) );
92 return d + (d >> 3);
96 typedef ::std::unordered_set<void const*, VoidPtrHash > VoidPointerSet;
98 struct ObjectRegistryData {
99 ObjectRegistryData( ::std::type_info const& rTypeInfo )
100 : m_pName(rTypeInfo.name()), m_nCount(0), m_addresses(),
101 m_bStoreAddresses(osl_detail_ObjectRegistry_storeAddresses(m_pName)) {}
103 char const* const m_pName;
104 oslInterlockedCount m_nCount;
105 VoidPointerSet m_addresses;
106 bool const m_bStoreAddresses;
109 template <typename T>
110 class ObjectRegistry
112 public:
113 ObjectRegistry() : m_data( typeid(T) ) {}
114 ~ObjectRegistry() { checkObjectCount(0); }
116 bool checkObjectCount( ::std::size_t nExpected ) const {
117 bool const bRet = osl_detail_ObjectRegistry_checkObjectCount(
118 m_data, nExpected );
119 if (!bRet && m_data.m_bStoreAddresses) {
120 MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
121 // following loop is for debugging purposes, iterating over map:
122 VoidPointerSet::const_iterator iPos(m_data.m_addresses.begin());
123 VoidPointerSet::const_iterator const iEnd(m_data.m_addresses.end());
124 for ( ; iPos != iEnd; ++iPos ) {
125 SAL_WARN_IF( *iPos == NULL, "sal.debug", "null pointer" );
128 return bRet;
131 void registerObject( void const* pObj ) {
132 osl_detail_ObjectRegistry_registerObject(m_data, pObj);
135 void revokeObject( void const* pObj ) {
136 osl_detail_ObjectRegistry_revokeObject(m_data, pObj);
139 private:
140 ObjectRegistry( ObjectRegistry const& ) SAL_DELETED_FUNCTION;
141 ObjectRegistry const& operator=( ObjectRegistry const& ) SAL_DELETED_FUNCTION;
143 ObjectRegistryData m_data;
146 } // namespace detail
148 /** Helper class which indicates leaking object(s) of a particular class in
149 non-pro builds; use e.g.
151 @code{.cpp}
152 class MyClass : private osl::DebugBase<MyClass> {...};
153 @endcode
155 Using the environment variable
157 OSL_DEBUGBASE_STORE_ADDRESSES=MyClass;YourClass;...
159 you can specify a ';'-separated list of strings matching to class names
160 (or "all" for all classes), for which DebugBase stores addresses to created
161 objects instead of just counting them. This enables you to iterate over
162 leaking objects in your debugger.
164 @tparam InheritingClassT binds the template instance to that class
165 @attention Use at own risk.
166 For now this is just public (yet unpublished) API and may change
167 in the future!
169 template <typename InheritingClassT>
170 class DebugBase
172 public:
173 #if OSL_DEBUG_LEVEL <= 0
174 static bool checkObjectCount( ::std::size_t = 0 ) { return true; }
175 #else // OSL_DEBUG_LEVEL > 0
176 /** @return whether the expected number of objects is alive,
177 else this function SAL_WARNs
179 static bool checkObjectCount( ::std::size_t nExpected = 0 ) {
180 return StaticObjectRegistry::get().checkObjectCount(nExpected);
183 protected:
184 DebugBase() {
185 StaticObjectRegistry::get().registerObject( this );
187 ~DebugBase() {
188 StaticObjectRegistry::get().revokeObject( this );
191 private:
192 struct StaticObjectRegistry
193 : ::rtl::Static<detail::ObjectRegistry<InheritingClassT>,
194 StaticObjectRegistry> {};
195 #endif
198 } // namespace osl
200 /// @endcond
202 #endif // ! defined( INCLUDED_OSL_DIAGNOSE_HXX)
204 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */