1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sal.hxx"
26
27 #include "rtl/strbuf.hxx"
28 #include "rtl/string.hxx"
29 #include "rtl/ustring.hxx"
30 #include "osl/process.h"
31 #include "osl/diagnose.hxx"
32 #include "boost/bind.hpp"
33 #include <vector>
34 #include <algorithm>
35
36 // define own ones, independent of OSL_DEBUG_LEVEL:
37 #define DEBUGBASE_ENSURE_(c, f, l, m) \
38 do \
39 { \
40 if (!(c) && _OSL_GLOBAL osl_assertFailedLine(f, l, m)) \
41 _OSL_GLOBAL osl_breakDebug(); \
42 } while (0)
43 #define DEBUGBASE_ENSURE(c, m) DEBUGBASE_ENSURE_(c, OSL_THIS_FILE, __LINE__, m)
44
45 namespace {
46
47 typedef std::vector<rtl::OString> OStringVec;
48
49 struct StaticDebugBaseAddressFilter
50 : rtl::StaticWithInit<OStringVec const, StaticDebugBaseAddressFilter> {
operator ()__anon6fe5e5ee0111::StaticDebugBaseAddressFilter51 OStringVec const operator()() const {
52 OStringVec vec;
53 rtl_uString * pStr = 0;
54 rtl::OUString const name(
55 RTL_CONSTASCII_USTRINGPARAM("OSL_DEBUGBASE_STORE_ADDRESSES") );
56 if (osl_getEnvironment( name.pData, &pStr ) == osl_Process_E_None) {
57 rtl::OUString const str(pStr);
58 rtl_uString_release(pStr);
59 sal_Int32 nIndex = 0;
60 do {
61 vec.push_back( rtl::OUStringToOString(
62 str.getToken( 0, ';', nIndex ),
63 RTL_TEXTENCODING_ASCII_US ) );
64 }
65 while (nIndex >= 0);
66 }
67 return vec;
68 }
69 };
70
isSubStr(char const * pStr,rtl::OString const & subStr)71 inline bool isSubStr( char const* pStr, rtl::OString const& subStr )
72 {
73 return rtl_str_indexOfStr( pStr, subStr.getStr() ) >= 0;
74 }
75
76 struct DebugBaseMutex : ::rtl::Static<osl::Mutex, DebugBaseMutex> {};
77
78 } // anon namespace
79
80 extern "C" {
81
osl_detail_ObjectRegistry_getMutex()82 osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex()
83 SAL_THROW_EXTERN_C()
84 {
85 return DebugBaseMutex::get();
86 }
87
osl_detail_ObjectRegistry_storeAddresses(char const * pName)88 bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses( char const* pName )
89 SAL_THROW_EXTERN_C()
90 {
91 OStringVec const& rVec = StaticDebugBaseAddressFilter::get();
92 if (rVec.empty())
93 return false;
94 // check for "all":
95 rtl::OString const& rFirst = rVec[0];
96 if (rtl_str_compare_WithLength( rFirst.getStr(), rFirst.getLength(),
97 RTL_CONSTASCII_STRINGPARAM("all") ) == 0)
98 return true;
99 OStringVec::const_iterator const iEnd( rVec.end() );
100 return std::find_if( rVec.begin(), iEnd,
101 boost::bind( &isSubStr, pName, _1 ) ) != iEnd;
102 }
103
osl_detail_ObjectRegistry_checkObjectCount(osl::detail::ObjectRegistryData const & rData,std::size_t nExpected)104 bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount(
105 osl::detail::ObjectRegistryData const& rData, std::size_t nExpected )
106 SAL_THROW_EXTERN_C()
107 {
108 std::size_t nSize;
109 if (rData.m_bStoreAddresses)
110 nSize = rData.m_addresses.size();
111 else
112 nSize = static_cast<std::size_t>(rData.m_nCount);
113
114 bool const bRet = (nSize == nExpected);
115 if (! bRet) {
116 rtl::OStringBuffer buf;
117 buf.append( RTL_CONSTASCII_STRINGPARAM("unexpected number of ") );
118 buf.append( rData.m_pName );
119 buf.append( RTL_CONSTASCII_STRINGPARAM(": ") );
120 buf.append( static_cast<sal_Int64>(nSize) );
121 DEBUGBASE_ENSURE( false, buf.makeStringAndClear().getStr() );
122 }
123 return bRet;
124 }
125
osl_detail_ObjectRegistry_registerObject(osl::detail::ObjectRegistryData & rData,void const * pObj)126 void SAL_CALL osl_detail_ObjectRegistry_registerObject(
127 osl::detail::ObjectRegistryData & rData, void const* pObj )
128 SAL_THROW_EXTERN_C()
129 {
130 if (rData.m_bStoreAddresses) {
131 osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
132 std::pair<osl::detail::VoidPointerSet::iterator, bool> const insertion(
133 rData.m_addresses.insert(pObj) );
134 DEBUGBASE_ENSURE( insertion.second, "### insertion failed!?" );
135 static_cast<void>(insertion);
136 }
137 else {
138 osl_incrementInterlockedCount(&rData.m_nCount);
139 }
140 }
141
osl_detail_ObjectRegistry_revokeObject(osl::detail::ObjectRegistryData & rData,void const * pObj)142 void SAL_CALL osl_detail_ObjectRegistry_revokeObject(
143 osl::detail::ObjectRegistryData & rData, void const* pObj )
144 SAL_THROW_EXTERN_C()
145 {
146 if (rData.m_bStoreAddresses) {
147 osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
148 std::size_t const n = rData.m_addresses.erase(pObj);
149 DEBUGBASE_ENSURE( n == 1, "erased more than 1 entry!?" );
150 static_cast<void>(n);
151 }
152 else {
153 osl_decrementInterlockedCount(&rData.m_nCount);
154 }
155 }
156
157 } // extern "C"
158
159