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, rtl::Allocator<rtl::OString> > OStringVec; 48 49 struct StaticDebugBaseAddressFilter 50 : rtl::StaticWithInit<OStringVec const, StaticDebugBaseAddressFilter> { 51 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 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 82 osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex() 83 SAL_THROW_EXTERN_C() 84 { 85 return DebugBaseMutex::get(); 86 } 87 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 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 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 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