blob: a0718acb0d7fca7e6d429a78a6e93d1b26d22975 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sal.hxx"
#include "rtl/strbuf.hxx"
#include "rtl/string.hxx"
#include "rtl/ustring.hxx"
#include "osl/process.h"
#include "osl/diagnose.hxx"
#include "boost/bind.hpp"
#include <vector>
#include <algorithm>
// define own ones, independent of OSL_DEBUG_LEVEL:
#define DEBUGBASE_ENSURE_(c, f, l, m) \
do \
{ \
if (!(c) && _OSL_GLOBAL osl_assertFailedLine(f, l, m)) \
_OSL_GLOBAL osl_breakDebug(); \
} while (0)
#define DEBUGBASE_ENSURE(c, m) DEBUGBASE_ENSURE_(c, OSL_THIS_FILE, __LINE__, m)
namespace {
typedef std::vector<rtl::OString> OStringVec;
struct StaticDebugBaseAddressFilter
: rtl::StaticWithInit<OStringVec const, StaticDebugBaseAddressFilter> {
OStringVec const operator()() const {
OStringVec vec;
rtl_uString * pStr = 0;
rtl::OUString const name(
RTL_CONSTASCII_USTRINGPARAM("OSL_DEBUGBASE_STORE_ADDRESSES") );
if (osl_getEnvironment( name.pData, &pStr ) == osl_Process_E_None) {
rtl::OUString const str(pStr);
rtl_uString_release(pStr);
sal_Int32 nIndex = 0;
do {
vec.push_back( rtl::OUStringToOString(
str.getToken( 0, ';', nIndex ),
RTL_TEXTENCODING_ASCII_US ) );
}
while (nIndex >= 0);
}
return vec;
}
};
inline bool isSubStr( char const* pStr, rtl::OString const& subStr )
{
return rtl_str_indexOfStr( pStr, subStr.getStr() ) >= 0;
}
struct DebugBaseMutex : ::rtl::Static<osl::Mutex, DebugBaseMutex> {};
} // anon namespace
extern "C" {
osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex()
SAL_THROW_EXTERN_C()
{
return DebugBaseMutex::get();
}
bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses( char const* pName )
SAL_THROW_EXTERN_C()
{
OStringVec const& rVec = StaticDebugBaseAddressFilter::get();
if (rVec.empty())
return false;
// check for "all":
rtl::OString const& rFirst = rVec[0];
if (rtl_str_compare_WithLength( rFirst.getStr(), rFirst.getLength(),
RTL_CONSTASCII_STRINGPARAM("all") ) == 0)
return true;
OStringVec::const_iterator const iEnd( rVec.end() );
return std::find_if( rVec.begin(), iEnd,
boost::bind( &isSubStr, pName, _1 ) ) != iEnd;
}
bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount(
osl::detail::ObjectRegistryData const& rData, std::size_t nExpected )
SAL_THROW_EXTERN_C()
{
std::size_t nSize;
if (rData.m_bStoreAddresses)
nSize = rData.m_addresses.size();
else
nSize = static_cast<std::size_t>(rData.m_nCount);
bool const bRet = (nSize == nExpected);
if (! bRet) {
rtl::OStringBuffer buf;
buf.append( RTL_CONSTASCII_STRINGPARAM("unexpected number of ") );
buf.append( rData.m_pName );
buf.append( RTL_CONSTASCII_STRINGPARAM(": ") );
buf.append( static_cast<sal_Int64>(nSize) );
DEBUGBASE_ENSURE( false, buf.makeStringAndClear().getStr() );
}
return bRet;
}
void SAL_CALL osl_detail_ObjectRegistry_registerObject(
osl::detail::ObjectRegistryData & rData, void const* pObj )
SAL_THROW_EXTERN_C()
{
if (rData.m_bStoreAddresses) {
osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
std::pair<osl::detail::VoidPointerSet::iterator, bool> const insertion(
rData.m_addresses.insert(pObj) );
DEBUGBASE_ENSURE( insertion.second, "### insertion failed!?" );
static_cast<void>(insertion);
}
else {
osl_incrementInterlockedCount(&rData.m_nCount);
}
}
void SAL_CALL osl_detail_ObjectRegistry_revokeObject(
osl::detail::ObjectRegistryData & rData, void const* pObj )
SAL_THROW_EXTERN_C()
{
if (rData.m_bStoreAddresses) {
osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
std::size_t const n = rData.m_addresses.erase(pObj);
DEBUGBASE_ENSURE( n == 1, "erased more than 1 entry!?" );
static_cast<void>(n);
}
else {
osl_decrementInterlockedCount(&rData.m_nCount);
}
}
} // extern "C"