1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sal.hxx" 30 31 #include "rtl/strbuf.hxx" 32 #include "rtl/string.hxx" 33 #include "rtl/ustring.hxx" 34 #include "osl/process.h" 35 #include "osl/diagnose.hxx" 36 #include "boost/bind.hpp" 37 #include <vector> 38 39 // define own ones, independent of OSL_DEBUG_LEVEL: 40 #define DEBUGBASE_ENSURE_(c, f, l, m) \ 41 do \ 42 { \ 43 if (!(c) && _OSL_GLOBAL osl_assertFailedLine(f, l, m)) \ 44 _OSL_GLOBAL osl_breakDebug(); \ 45 } while (0) 46 #define DEBUGBASE_ENSURE(c, m) DEBUGBASE_ENSURE_(c, OSL_THIS_FILE, __LINE__, m) 47 48 namespace { 49 50 typedef std::vector<rtl::OString, rtl::Allocator<rtl::OString> > OStringVec; 51 52 struct StaticDebugBaseAddressFilter 53 : rtl::StaticWithInit<OStringVec const, StaticDebugBaseAddressFilter> { 54 OStringVec const operator()() const { 55 OStringVec vec; 56 rtl_uString * pStr = 0; 57 rtl::OUString const name( 58 RTL_CONSTASCII_USTRINGPARAM("OSL_DEBUGBASE_STORE_ADDRESSES") ); 59 if (osl_getEnvironment( name.pData, &pStr ) == osl_Process_E_None) { 60 rtl::OUString const str(pStr); 61 rtl_uString_release(pStr); 62 sal_Int32 nIndex = 0; 63 do { 64 vec.push_back( rtl::OUStringToOString( 65 str.getToken( 0, ';', nIndex ), 66 RTL_TEXTENCODING_ASCII_US ) ); 67 } 68 while (nIndex >= 0); 69 } 70 return vec; 71 } 72 }; 73 74 inline bool isSubStr( char const* pStr, rtl::OString const& subStr ) 75 { 76 return rtl_str_indexOfStr( pStr, subStr.getStr() ) >= 0; 77 } 78 79 struct DebugBaseMutex : ::rtl::Static<osl::Mutex, DebugBaseMutex> {}; 80 81 } // anon namespace 82 83 extern "C" { 84 85 osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex() 86 SAL_THROW_EXTERN_C() 87 { 88 return DebugBaseMutex::get(); 89 } 90 91 bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses( char const* pName ) 92 SAL_THROW_EXTERN_C() 93 { 94 OStringVec const& rVec = StaticDebugBaseAddressFilter::get(); 95 if (rVec.empty()) 96 return false; 97 // check for "all": 98 rtl::OString const& rFirst = rVec[0]; 99 if (rtl_str_compare_WithLength( rFirst.getStr(), rFirst.getLength(), 100 RTL_CONSTASCII_STRINGPARAM("all") ) == 0) 101 return true; 102 OStringVec::const_iterator const iEnd( rVec.end() ); 103 return std::find_if( rVec.begin(), iEnd, 104 boost::bind( &isSubStr, pName, _1 ) ) != iEnd; 105 } 106 107 bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount( 108 osl::detail::ObjectRegistryData const& rData, std::size_t nExpected ) 109 SAL_THROW_EXTERN_C() 110 { 111 std::size_t nSize; 112 if (rData.m_bStoreAddresses) 113 nSize = rData.m_addresses.size(); 114 else 115 nSize = static_cast<std::size_t>(rData.m_nCount); 116 117 bool const bRet = (nSize == nExpected); 118 if (! bRet) { 119 rtl::OStringBuffer buf; 120 buf.append( RTL_CONSTASCII_STRINGPARAM("unexpected number of ") ); 121 buf.append( rData.m_pName ); 122 buf.append( RTL_CONSTASCII_STRINGPARAM(": ") ); 123 buf.append( static_cast<sal_Int64>(nSize) ); 124 DEBUGBASE_ENSURE( false, buf.makeStringAndClear().getStr() ); 125 } 126 return bRet; 127 } 128 129 void SAL_CALL osl_detail_ObjectRegistry_registerObject( 130 osl::detail::ObjectRegistryData & rData, void const* pObj ) 131 SAL_THROW_EXTERN_C() 132 { 133 if (rData.m_bStoreAddresses) { 134 osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() ); 135 std::pair<osl::detail::VoidPointerSet::iterator, bool> const insertion( 136 rData.m_addresses.insert(pObj) ); 137 DEBUGBASE_ENSURE( insertion.second, "### insertion failed!?" ); 138 static_cast<void>(insertion); 139 } 140 else { 141 osl_incrementInterlockedCount(&rData.m_nCount); 142 } 143 } 144 145 void SAL_CALL osl_detail_ObjectRegistry_revokeObject( 146 osl::detail::ObjectRegistryData & rData, void const* pObj ) 147 SAL_THROW_EXTERN_C() 148 { 149 if (rData.m_bStoreAddresses) { 150 osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() ); 151 std::size_t const n = rData.m_addresses.erase(pObj); 152 DEBUGBASE_ENSURE( n == 1, "erased more than 1 entry!?" ); 153 static_cast<void>(n); 154 } 155 else { 156 osl_decrementInterlockedCount(&rData.m_nCount); 157 } 158 } 159 160 } // extern "C" 161 162