summaryrefslogtreecommitdiffstats
path: root/include/osl/diagnose.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/osl/diagnose.h124
-rw-r--r--include/osl/diagnose.hxx200
2 files changed, 324 insertions, 0 deletions
diff --git a/include/osl/diagnose.h b/include/osl/diagnose.h
new file mode 100644
index 000000000..356f2945b
--- /dev/null
+++ b/include/osl/diagnose.h
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+/*
+ * This file is part of LibreOffice published API.
+ */
+
+#ifndef INCLUDED_OSL_DIAGNOSE_H
+#define INCLUDED_OSL_DIAGNOSE_H
+
+#include "sal/config.h"
+
+#include "sal/detail/log.h"
+#include "sal/types.h"
+
+/** @file
+ Provides simple diagnostic support.
+
+ @deprecated
+ The facilities provided by this header are deprecated. True assertions
+ (that detect broken program logic) should use standard assert (which aborts
+ if an assertion fails, and is controlled by the standard NDEBUG macro).
+ Logging of warnings (e.g., about malformed input) and traces (e.g., about
+ steps taken while executing some protocol) should use the facilities
+ provided by (C++ only) sal/log.hxx.
+
+ Because the assertion macros (OSL_ASSERT, OSL_ENSURE, OSL_FAIL, OSL_PRECOND,
+ and OSL_POSTCOND) have been used for true assertions as well as for logged
+ warnings, they map to SAL_WARN instead of standard assert. OSL_TRACE maps
+ to SAL_INFO.
+
+ The functions defined in this header are not intended to be used directly,
+ but through defined macros. The macros can be divided into three categories:
+ assertions, traces and other stuff .-) Their usability depends on the value
+ of OSL_DEBUG_LEVEL macro: assertions are only active if OSL_DEBUG_LEVEL is 1
+ or greater, traces if OSL_DEBUG_LEVEL is 2 or greater.
+
+ Traces:
+ OSL_TRACE(fmt, args...)
+ Prints trace message. The arguments have the same meaning as the
+ arguments of printf.
+ */
+
+#if !defined OSL_DEBUG_LEVEL
+#define OSL_DEBUG_LEVEL 0
+#endif
+
+/** @internal The macro OSL_LOG_PREFIX is intended to be an office internal macro for now
+ @deprecated superseded by (C++ only) SAL_WHERE
+*/
+#define OSL_LOG_PREFIX SAL_DETAIL_WHERE
+
+/** Prints trace message.
+
+ The arguments have the same meaning as the arguments of printf.
+*/
+#define OSL_TRACE(...) \
+ SAL_DETAIL_INFO_IF_FORMAT(OSL_DEBUG_LEVEL > 0, "legacy.osl", __VA_ARGS__)
+
+/** @defgroup assert Assertions
+
+ Assertions (cond is bool, msg is char*).
+
+ @{
+ */
+
+/** If cond is false, reports an error. */
+#define OSL_ASSERT(c) \
+ SAL_DETAIL_WARN_IF_FORMAT(!(c), "legacy.osl", "OSL_ASSERT: %s", #c)
+/** If cond is false, reports an error with message msg. */
+#define OSL_ENSURE(c, m) SAL_DETAIL_WARN_IF_FORMAT(!(c), "legacy.osl", "%s", m)
+/** Reports an error with message msg unconditionally. */
+#define OSL_FAIL(m) SAL_DETAIL_WARN_IF_FORMAT(sal_True, "legacy.osl", "%s", m)
+
+/** Evaluates the expression and if it is false, reports an error. The
+ expression is evaluated once without regard of the value of
+ OSL_DEBUG_LEVEL.
+
+ Example:
+
+ @code{.c}
+
+ void extractBool(Any const& rAny, bool& rBool)
+ {
+ OSL_VERIFY(rAny >>= rBool);
+ }
+
+ @endcode
+*/
+#define OSL_VERIFY(c) do { if (!(c)) OSL_ASSERT(0); } while (0)
+
+/** Check the precondition of functions.
+
+ Functionally equivalent to OSL_ENSURE(cond, msg).
+*/
+#define OSL_PRECOND(c, m) OSL_ENSURE(c, m)
+
+/** Check the postcondition of functions.
+
+ Functionally equivalent to OSL_ENSURE(cond, msg).
+*/
+#define OSL_POSTCOND(c, m) OSL_ENSURE(c, m)
+
+/** @} */
+
+#endif // INCLUDED_OSL_DIAGNOSE_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/osl/diagnose.hxx b/include/osl/diagnose.hxx
new file mode 100644
index 000000000..71d49f3d8
--- /dev/null
+++ b/include/osl/diagnose.hxx
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+#ifndef INCLUDED_OSL_DIAGNOSE_HXX
+#define INCLUDED_OSL_DIAGNOSE_HXX
+
+/// @cond INTERNAL
+
+#include "sal/config.h"
+
+#include <cstddef>
+#include <typeinfo>
+#include <unordered_set>
+
+#include "osl/diagnose.h"
+#include "osl/interlck.h"
+#include "osl/mutex.hxx"
+#include "rtl/instance.hxx"
+#include "sal/log.hxx"
+#include "sal/saldllapi.h"
+#include "sal/types.h"
+
+namespace osl {
+namespace detail {
+
+struct ObjectRegistryData;
+
+} // namespace detail
+} // namespace osl
+
+extern "C" {
+
+SAL_DLLPUBLIC bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses(
+ char const* pName )
+ SAL_THROW_EXTERN_C();
+
+SAL_DLLPUBLIC bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount(
+ ::osl::detail::ObjectRegistryData const& rData, ::std::size_t nExpected )
+ SAL_THROW_EXTERN_C();
+
+SAL_DLLPUBLIC void SAL_CALL osl_detail_ObjectRegistry_registerObject(
+ ::osl::detail::ObjectRegistryData & rData, void const* pObj )
+ SAL_THROW_EXTERN_C();
+
+SAL_DLLPUBLIC void SAL_CALL osl_detail_ObjectRegistry_revokeObject(
+ ::osl::detail::ObjectRegistryData & rData, void const* pObj )
+ SAL_THROW_EXTERN_C();
+
+// These functions presumably should not be extern "C", but changing
+// that would break binary compatibility.
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
+#endif
+
+SAL_DLLPUBLIC ::osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex()
+ SAL_THROW_EXTERN_C();
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+} // extern "C"
+
+namespace osl {
+
+namespace detail {
+
+struct VoidPtrHash {
+ ::std::size_t operator()( void const* p ) const {
+ ::std::size_t const d = static_cast< ::std::size_t >(
+ reinterpret_cast< ::std::ptrdiff_t >(p) );
+ return d + (d >> 3);
+ }
+};
+
+typedef ::std::unordered_set<void const*, VoidPtrHash > VoidPointerSet;
+
+struct ObjectRegistryData {
+ ObjectRegistryData( ::std::type_info const& rTypeInfo )
+ : m_pName(rTypeInfo.name()), m_nCount(0),
+ m_bStoreAddresses(osl_detail_ObjectRegistry_storeAddresses(m_pName)) {}
+
+ char const* const m_pName;
+ oslInterlockedCount m_nCount;
+ VoidPointerSet m_addresses;
+ bool const m_bStoreAddresses;
+};
+
+template <typename T>
+class ObjectRegistry
+{
+public:
+ ObjectRegistry() : m_data( typeid(T) ) {}
+ ~ObjectRegistry() { checkObjectCount(0); }
+
+ bool checkObjectCount( ::std::size_t nExpected ) const {
+ bool const bRet = osl_detail_ObjectRegistry_checkObjectCount(
+ m_data, nExpected );
+ if (!bRet && m_data.m_bStoreAddresses) {
+ MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
+ // following loop is for debugging purposes, iterating over map:
+ VoidPointerSet::const_iterator iPos(m_data.m_addresses.begin());
+ VoidPointerSet::const_iterator const iEnd(m_data.m_addresses.end());
+ for ( ; iPos != iEnd; ++iPos ) {
+ SAL_WARN_IF( *iPos == NULL, "sal.debug", "null pointer" );
+ }
+ }
+ return bRet;
+ }
+
+ void registerObject( void const* pObj ) {
+ osl_detail_ObjectRegistry_registerObject(m_data, pObj);
+ }
+
+ void revokeObject( void const* pObj ) {
+ osl_detail_ObjectRegistry_revokeObject(m_data, pObj);
+ }
+
+private:
+ ObjectRegistry( ObjectRegistry const& ) SAL_DELETED_FUNCTION;
+ ObjectRegistry const& operator=( ObjectRegistry const& ) SAL_DELETED_FUNCTION;
+
+ ObjectRegistryData m_data;
+};
+
+} // namespace detail
+
+/** Helper class which indicates leaking object(s) of a particular class in
+ non-pro builds; use e.g.
+
+ @code{.cpp}
+ class MyClass : private osl::DebugBase<MyClass> {...};
+ @endcode
+
+ Using the environment variable
+
+ OSL_DEBUGBASE_STORE_ADDRESSES=MyClass;YourClass;...
+
+ you can specify a ';'-separated list of strings matching to class names
+ (or "all" for all classes), for which DebugBase stores addresses to created
+ objects instead of just counting them. This enables you to iterate over
+ leaking objects in your debugger.
+
+ @tparam InheritingClassT binds the template instance to that class
+ @attention Use at own risk.
+ For now this is just public (yet unpublished) API and may change
+ in the future!
+*/
+template <typename InheritingClassT>
+class DebugBase
+{
+public:
+#if OSL_DEBUG_LEVEL <= 0
+ static bool checkObjectCount( ::std::size_t = 0 ) { return true; }
+#else // OSL_DEBUG_LEVEL > 0
+ /** @return whether the expected number of objects is alive,
+ else this function SAL_WARNs
+ */
+ static bool checkObjectCount( ::std::size_t nExpected = 0 ) {
+ return StaticObjectRegistry::get().checkObjectCount(nExpected);
+ }
+
+protected:
+ DebugBase() {
+ StaticObjectRegistry::get().registerObject( this );
+ }
+ ~DebugBase() {
+ StaticObjectRegistry::get().revokeObject( this );
+ }
+
+private:
+ struct StaticObjectRegistry
+ : ::rtl::Static<detail::ObjectRegistry<InheritingClassT>,
+ StaticObjectRegistry> {};
+#endif
+};
+
+} // namespace osl
+
+/// @endcond
+
+#endif // ! defined( INCLUDED_OSL_DIAGNOSE_HXX)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */