mirror of
https://github.com/ashaduri/gsmartcontrol.git
synced 2026-09-29 07:05:34 +00:00
First round of porting to C++17 and removing old code.
This commit is contained in:
@@ -26,6 +26,31 @@ TODO:
|
||||
Don't rely on smartctl return code (2), parse the output instead.
|
||||
This will allow us to show the Info page.
|
||||
Need usage cases.
|
||||
JSON may fix this.
|
||||
|
||||
|
||||
Port to C++17 (or at least 14, that's what libsigc++ requires)
|
||||
Remove glibmm thread stuff (it's gone in gtkmm4).
|
||||
|
||||
|
||||
Remove strtold / strtof.
|
||||
DISABLE_STRTOF
|
||||
DISABLE_STRTOLD
|
||||
Port to std::filesystem.
|
||||
convert hz::any_type to std::any
|
||||
type_properties.h
|
||||
static_assert
|
||||
scoped_ptr
|
||||
cstdint
|
||||
|
||||
|
||||
After JSON:
|
||||
Port to std::regex, get rid of pcre requirement.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Testing:
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# ===========================================================================
|
||||
# http://autoconf-archive.cryp.to/ac_cxx_exceptions.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AC_CXX_EXCEPTIONS
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# If the C++ compiler supports exceptions handling (try, throw and catch),
|
||||
# define HAVE_EXCEPTIONS.
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2008-04-12
|
||||
#
|
||||
# COPYLEFT
|
||||
#
|
||||
# Copyright (c) 2008 Todd Veldhuizen
|
||||
# Copyright (c) 2008 Luc Maisonobe <luc@spaceroots.org>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved.
|
||||
|
||||
AC_DEFUN([AC_CXX_EXCEPTIONS],
|
||||
[AC_CACHE_CHECK(whether the compiler supports exceptions,
|
||||
ac_cv_cxx_exceptions,
|
||||
[AC_LANG_PUSH([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],
|
||||
[[try { throw 1; } catch (int i) { return i; }]])],
|
||||
[ac_cv_cxx_exceptions=yes], [ac_cv_cxx_exceptions=no])
|
||||
AC_LANG_POP([])
|
||||
])
|
||||
|
||||
if test "$ac_cv_cxx_exceptions" = yes; then
|
||||
AC_DEFINE(HAVE_EXCEPTIONS, 1,
|
||||
[defined to 1 if the compiler supports exceptions, 0 otherwise])
|
||||
else
|
||||
AC_DEFINE(HAVE_EXCEPTIONS, 0,
|
||||
[defined to 1 if the compiler supports exceptions, 0 otherwise])
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# ===========================================================================
|
||||
# http://autoconf-archive.cryp.to/ac_cxx_namespaces.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AC_CXX_NAMESPACES
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# If the compiler can prevent names clashes using namespaces, define
|
||||
# HAVE_NAMESPACES.
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2008-04-12
|
||||
#
|
||||
# COPYLEFT
|
||||
#
|
||||
# Copyright (c) 2008 Todd Veldhuizen
|
||||
# Copyright (c) 2008 Luc Maisonobe <luc@spaceroots.org>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved.
|
||||
|
||||
AC_DEFUN([AC_CXX_NAMESPACES],
|
||||
[AC_CACHE_CHECK(whether the compiler implements namespaces,
|
||||
ac_cv_cxx_namespaces,
|
||||
[AC_LANG_PUSH([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[namespace Outer { namespace Inner { int i = 0; }}]],
|
||||
[[using namespace Outer::Inner; return i;]])],
|
||||
[ac_cv_cxx_namespaces=yes], [ac_cv_cxx_namespaces=no])
|
||||
AC_LANG_POP([])
|
||||
])
|
||||
if test "$ac_cv_cxx_namespaces" = yes; then
|
||||
AC_DEFINE(HAVE_NAMESPACES, 1,
|
||||
[defined to 1 if the compiler implements namespaces, 0 otherwise])
|
||||
else
|
||||
AC_DEFINE(HAVE_NAMESPACES, 0,
|
||||
[defined to 1 if the compiler implements namespaces, 0 otherwise])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
# ===========================================================================
|
||||
# http://autoconf-archive.cryp.to/ac_cxx_rtti.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AC_CXX_RTTI
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# If the compiler supports Run-Time Type Identification (typeinfo header
|
||||
# and typeid keyword), define HAVE_RTTI.
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2008-04-12
|
||||
#
|
||||
# COPYLEFT
|
||||
#
|
||||
# Copyright (c) 2008 Todd Veldhuizen
|
||||
# Copyright (c) 2008 Luc Maisonobe <luc@spaceroots.org>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved.
|
||||
|
||||
AC_DEFUN([AC_CXX_RTTI],
|
||||
[AC_CACHE_CHECK(whether the compiler supports Run-Time Type Identification,
|
||||
ac_cv_cxx_rtti,
|
||||
[AC_LANG_PUSH([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <typeinfo>
|
||||
class Base {
|
||||
public:
|
||||
Base () {}
|
||||
virtual int f () { return 0; }
|
||||
};
|
||||
class Derived : public Base {
|
||||
public :
|
||||
Derived () {}
|
||||
virtual int f () { return 1; }
|
||||
};
|
||||
]], [[
|
||||
Derived d;
|
||||
Base* ptr = &d;
|
||||
return typeid (*ptr) == typeid (Derived);
|
||||
]])],
|
||||
[ac_cv_cxx_rtti=yes], [ac_cv_cxx_rtti=no])
|
||||
AC_LANG_POP([])
|
||||
])
|
||||
if test "$ac_cv_cxx_rtti" = yes; then
|
||||
AC_DEFINE(HAVE_RTTI, 1,
|
||||
[defined to 1 if the compiler supports Run-Time Type Identification, 0 otherwise])
|
||||
else
|
||||
AC_DEFINE(HAVE_RTTI, 0,
|
||||
[defined to 1 if the compiler supports Run-Time Type Identification, 0 otherwise])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
|
||||
@@ -27,8 +27,6 @@ AC_DEFUN([AC_CXX_VERBOSE_TERMINATE_HANDLER],
|
||||
[AC_CACHE_CHECK(whether the compiler has __gnu_cxx::__verbose_terminate_handler,
|
||||
ac_cv_verbose_terminate_handler,
|
||||
[
|
||||
AC_REQUIRE([AC_CXX_EXCEPTIONS])
|
||||
AC_REQUIRE([AC_CXX_NAMESPACES])
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <exception>]],
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
|
||||
############################################################################
|
||||
# Copyright:
|
||||
# (C) 2008 - 2009 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
# License: See LICENSE_zlib.txt file
|
||||
############################################################################
|
||||
|
||||
|
||||
# Check whether C++ compiler supports C99 __func__.
|
||||
|
||||
AC_DEFUN([APP_CXX___func__], [
|
||||
AC_CACHE_CHECK(whether $CXX recognizes __func__, app_cv_cxx___func__, [
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],
|
||||
[[const char* s = __func__;]])],
|
||||
[app_cv_cxx___func__=yes], [app_cv_cxx___func__=no])
|
||||
AC_LANG_POP([])
|
||||
])
|
||||
if test "x$app_cv_cxx___func__" = "xyes"; then
|
||||
AC_DEFINE(HAVE_CXX___func__, 1,
|
||||
[Defined to 1 if the C++ complier supports __func__, 0 otherwise])
|
||||
else
|
||||
AC_DEFINE(HAVE_CXX___func__, 0,
|
||||
[Defined to 1 if the C++ complier supports __func__, 0 otherwise])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
|
||||
# Check whether C++ compiler supports __FUNCTION__.
|
||||
|
||||
AC_DEFUN([APP_CXX___FUNCTION__], [
|
||||
AC_CACHE_CHECK(whether $CXX recognizes __FUNCTION__, app_cv_cxx___FUNCTION__, [
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],
|
||||
[[const char* s = __FUNCTION__;]])],
|
||||
[app_cv_cxx___FUNCTION__=yes], [app_cv_cxx___FUNCTION__=no])
|
||||
AC_LANG_POP([])
|
||||
])
|
||||
if test "x$app_cv_cxx___FUNCTION__" = "xyes"; then
|
||||
AC_DEFINE(HAVE_CXX___FUNCTION__, 1,
|
||||
[Defined to 1 if the C++ complier supports __FUNCTION__, 0 otherwise])
|
||||
else
|
||||
AC_DEFINE(HAVE_CXX___FUNCTION__, 0,
|
||||
[Defined to 1 if the C++ complier supports __FUNCTION__, 0 otherwise])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||
[define if the compiler supports basic C++$1 syntax])
|
||||
fi
|
||||
AC_SUBST(HAVE_CXX$1)
|
||||
m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
|
||||
#m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
|
||||
])
|
||||
|
||||
|
||||
|
||||
+15
-68
@@ -1,5 +1,5 @@
|
||||
|
||||
AC_INIT([GSmartControl],[1.1.3],[],[gsmartcontrol])
|
||||
AC_INIT([GSmartControl],[2.0.0],[],[gsmartcontrol])
|
||||
|
||||
AC_CONFIG_SRCDIR([configure.ac])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@@ -41,14 +41,17 @@ AC_CHECK_TOOL(WINDRES, windres)
|
||||
AC_PROG_LN_S
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------- Detect compiler, OS, environment. Enable system features.
|
||||
|
||||
|
||||
# Enable C++17 support.
|
||||
# This has to be AFTER gtkmm, since gtkmm has its own C++ flags.
|
||||
AX_CXX_COMPILE_STDCXX([17], [], [mandatory])
|
||||
|
||||
|
||||
# detect compiler vendor (sets $ax_cv_cxx_compiler_vendor)
|
||||
AX_COMPILER_VENDOR
|
||||
|
||||
@@ -64,10 +67,6 @@ APP_DETECT_OS_KERNEL([build], [CONFIG_HOST_KERNEL_])
|
||||
# which is important for some compatibility flags (e.g. __func__ visibility, etc...).
|
||||
APP_COMPILER_OPTIONS([])
|
||||
|
||||
# Enable C++11 support. This is implied by gtkmm3, but CentOS7 fails to add it
|
||||
# to gtkmm flags, so we have to enable it manually. Make it optional for Debian 7 (gcc 4.7).
|
||||
AX_CXX_COMPILE_STDCXX([11], [], [optional])
|
||||
|
||||
# Thread support for known configurations.
|
||||
# Sun compiler (at least on linux) has some runtime issues with stringstream
|
||||
# unless we use the thread flags. Also, Linux-based gdb fails to debug
|
||||
@@ -84,34 +83,8 @@ APP_USE_SYSTEM_EXTENSIONS([])
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
|
||||
|
||||
# ------------- Correct incomplete standard libraries
|
||||
|
||||
# define int8_t and friends if the standard doesn't have them
|
||||
AC_TYPE_INT8_T
|
||||
AC_TYPE_UINT8_T
|
||||
AC_TYPE_INT16_T
|
||||
AC_TYPE_UINT16_T
|
||||
AC_TYPE_INT32_T
|
||||
AC_TYPE_UINT32_T
|
||||
AC_TYPE_INT64_T
|
||||
AC_TYPE_UINT64_T
|
||||
AC_TYPE_INTMAX_T
|
||||
AC_TYPE_UINTMAX_T
|
||||
|
||||
AC_TYPE_LONG_LONG_INT
|
||||
AC_TYPE_UNSIGNED_LONG_LONG_INT
|
||||
|
||||
|
||||
|
||||
# ------------- Language / Standard Library checks
|
||||
|
||||
# detect RTTI (defines HAVE_RTTI)
|
||||
AC_CXX_RTTI
|
||||
|
||||
# detect exception support (defines HAVE_EXCEPTIONS)
|
||||
AC_CXX_EXCEPTIONS
|
||||
|
||||
# detect abi::__cxa_demangle (defines HAVE_GCC_ABI_DEMANGLE)
|
||||
AX_CXX_GCC_ABI_DEMANGLE
|
||||
|
||||
@@ -129,22 +102,6 @@ APP_CXX___FUNCTION__
|
||||
APP_CXX_EXTERN_C_OVERLOAD
|
||||
|
||||
|
||||
# This may be needed for pch support
|
||||
AC_CHECK_HEADERS([stdc++.h])
|
||||
|
||||
# Non-C99 systems don't have strtof and strtold. some have strtodf for strtof,
|
||||
# but let's ignore it. Note: They may be supported by system libc,
|
||||
# but not enabled by default (e.g. by glibc feature macros). In that case,
|
||||
# defining them still leads to undefined symbols at link time, so we don't do it.
|
||||
# Header check is the best way to determine availability.
|
||||
# This defines HAVE_DECL_<symbol> to 1 or 0.
|
||||
AC_CHECK_DECLS([strtof, strtold], [], [], [[#include <stdlib.h>]])
|
||||
# link check only:
|
||||
# AC_CHECK_FUNCS([strtof strtold])
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -154,8 +111,6 @@ AC_CHECK_DECLS([strtof, strtold], [], [], [[#include <stdlib.h>]])
|
||||
AC_CHECK_LIB(util, getrawpartition, [ LIBS="$LIBS -lutil" ])
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -166,8 +121,6 @@ AC_ARG_ENABLE([tests], AS_HELP_STRING([--enable-tests],
|
||||
AM_CONDITIONAL([ENABLE_TESTS], [test "$with_tests" = "yes"])
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -207,9 +160,6 @@ CXXFLAGS="$GTKMM_CFLAGS $CXXFLAGS"
|
||||
LIBS="$GTKMM_LIBS $LIBS"
|
||||
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -238,6 +188,15 @@ LIBS="$LIBS $PCRECPP_LIBS"
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# gtkmm may have an older -std standard in its CXXFLAGS which screws up
|
||||
# our -std flag in CXX. Override it.
|
||||
# Ideally, gcc should use the "latest" standard, but it just uses the latest option.
|
||||
# TODO For now, since gtkmm3 uses dynamic exception specifications, we have
|
||||
# to enable 14 instead of 17.
|
||||
CXXFLAGS="$CXXFLAGS -std=c++14"
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -288,8 +247,6 @@ AC_SUBST(WINDOWS_SYSROOT)
|
||||
AC_SUBST(WINDOWS_SUFFIX)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -305,8 +262,6 @@ fi
|
||||
AC_SUBST(WINDOWS_ARCH)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -368,8 +323,6 @@ AC_SUBST(RES_TARGETS)
|
||||
_AM_SUBST_NOTMAKE([RES_TARGETS])
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -409,8 +362,6 @@ ADDITIONAL_INCLUDES="-I\$(top_builddir) -I\$(top_srcdir)/src"
|
||||
CXXFLAGS="$ADDITIONAL_INCLUDES $CXXFLAGS"
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -432,8 +383,6 @@ AC_SUBST(LIBS)
|
||||
AC_SUBST(LDFLAGS)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -469,8 +418,6 @@ $LIBS
|
||||
AC_SUBST(AUTODIRS)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#include <string>
|
||||
#include <gtkmm.h>
|
||||
|
||||
#include "hz/down_cast.h"
|
||||
|
||||
|
||||
|
||||
/// Get column header widget of a tree view column.
|
||||
@@ -56,8 +54,7 @@ int app_gtkmm_create_tree_view_column(Gtk::TreeModelColumn<T>& mcol, Gtk::TreeVi
|
||||
app_gtkmm_set_widget_tooltip(*header, tooltip_text);
|
||||
|
||||
if (cell_markup) {
|
||||
Gtk::CellRendererText* cr_type = hz::down_cast<Gtk::CellRendererText*>(treeview.get_column_cell_renderer(num_tree_cols - 1));
|
||||
if (cr_type) { // may not be true if it's not Text (unless static_cast is used, in which case we're screwed)
|
||||
if (Gtk::CellRendererText* cr_type = dynamic_cast<Gtk::CellRendererText*>(treeview.get_column_cell_renderer(num_tree_cols - 1))) {
|
||||
treeview.get_column(num_tree_cols - 1)->clear_attributes(*cr_type); // clear "text" attribute. "markup" won't work without this.
|
||||
treeview.get_column(num_tree_cols - 1)->add_attribute(cr_type->property_markup(), mcol); // render col_type as markup.
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "hz/debug.h"
|
||||
#include "hz/instance_manager.h"
|
||||
#include "hz/down_cast.h"
|
||||
#include "hz/res_data.h"
|
||||
|
||||
#include "gui_utils.h" // gui_show_error_dialog
|
||||
@@ -218,7 +217,7 @@ class AppUIResWidget : public WidgetType, public hz::InstanceManager<Child, Mult
|
||||
template<typename ObjectPtr>
|
||||
ObjectPtr lookup_object(const Glib::ustring& name, ObjectPtr& obj)
|
||||
{
|
||||
return (obj = hz::down_cast<ObjectPtr>(lookup_object(name))); // up, then down
|
||||
return (obj = dynamic_cast<ObjectPtr>(lookup_object(name))); // up, then down
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#endif
|
||||
|
||||
#include "hz/process_signal.h" // hz::process_signal_send, win32's W*
|
||||
#include "hz/tls.h"
|
||||
#include "hz/tls_policy_glib.h"
|
||||
#include "hz/debug.h"
|
||||
#include "hz/string_num.h" // hz::number_to_string()
|
||||
#include "hz/env_tools.h" // hz::ScopedEnv
|
||||
|
||||
@@ -28,33 +28,6 @@ Additionally, it may be included through compiler's "-include" option
|
||||
#define APP_GLOBAL_MACROS_INCLUDED 1
|
||||
|
||||
|
||||
// #ifdef _WIN32
|
||||
// needed for hz::send_process_signal(), winxp or later.
|
||||
// #define WINVER 0x0501
|
||||
// #endif
|
||||
|
||||
// this is either defined to 1 (by autoconf), or undefined
|
||||
#ifdef HAVE_LONG_LONG_INT
|
||||
#define DISABLE_LL_INT 0
|
||||
|
||||
#else // there is no long long int
|
||||
// explicitly disable it in our code. by default, it assumes that long long int exists.
|
||||
#define DISABLE_LL_INT 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// this is either defined to 1 (by autoconf), or undefined
|
||||
#ifdef HAVE_UNSIGNED_LONG_LONG_INT
|
||||
#define DISABLE_ULL_INT 0
|
||||
|
||||
#else // there is no long long int
|
||||
// explicitly disable it in our code. by default, it assumes that long long int exists.
|
||||
#define DISABLE_ULL_INT 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// HAVE_func means that func doesn't throw undefined symbol.
|
||||
// HAVE_DECL_func means that it's declared in a header.
|
||||
@@ -91,30 +64,10 @@ Additionally, it may be included through compiler's "-include" option
|
||||
// #define ENABLE_GLIBMM 1
|
||||
|
||||
|
||||
// -- RMN settings - see rmn/rmn.h for details
|
||||
// #define RMN_TYPE_TRACKING
|
||||
|
||||
|
||||
// Note: We use DISABLE_* because all the libraries should assume
|
||||
// complete C++ support, unless indicated otherwise. This also
|
||||
// makes the headers work in full when there is no config.h.
|
||||
|
||||
// -- Define this if using -fno-rtti or similar (automatic from autoconf).
|
||||
// HAVE_RTTI is always defined as 1 or 0.
|
||||
#if !defined DISABLE_RTTI && defined HAVE_RTTI && !HAVE_RTTI
|
||||
#define DISABLE_RTTI 1
|
||||
#else
|
||||
#define DISABLE_RTTI 0
|
||||
#endif
|
||||
|
||||
// -- Define this if using -fno-exceptions (automatic from autoconf).
|
||||
// HAVE_EXCEPTIONS is always defined as 1 or 0.
|
||||
#if !defined DISABLE_EXCEPTIONS && defined HAVE_EXCEPTIONS && !HAVE_EXCEPTIONS
|
||||
#define DISABLE_EXCEPTIONS 1
|
||||
#else
|
||||
#define DISABLE_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// -- Default policy for synchronization primitives (sync.h);
|
||||
@@ -145,34 +98,6 @@ Additionally, it may be included through compiler's "-include" option
|
||||
*/
|
||||
|
||||
|
||||
// -- Default policy for thread-local storage pointer (tls.h);
|
||||
// (define only one of these):
|
||||
/*
|
||||
// check if any of them are forced
|
||||
#if (!defined HZ_TLS_DEFAULT_POLICY_BOOST) \
|
||||
&& (!defined HZ_TLS_DEFAULT_POLICY_GLIB) \
|
||||
&& (!defined HZ_TLS_DEFAULT_POLICY_PTHREAD) \
|
||||
&& (!defined HZ_TLS_DEFAULT_POLICY_WIN32)
|
||||
|
||||
#if defined ENABLE_GLIB && ENABLE_GLIB
|
||||
#define HZ_TLS_DEFAULT_POLICY_GLIB
|
||||
|
||||
#elif defined _WIN32
|
||||
// use pthread-win32 or boost on win32.
|
||||
// our win32 policy lacks good cleanup function support.
|
||||
#define HZ_TLS_DEFAULT_POLICY_PTHREAD
|
||||
|
||||
#else
|
||||
#define HZ_TLS_DEFAULT_POLICY_PTHREAD
|
||||
#endif
|
||||
|
||||
// #define HZ_TLS_DEFAULT_POLICY_BOOST
|
||||
// #define HZ_TLS_DEFAULT_POLICY_WIN32
|
||||
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
// -- hz/debug.h settings.
|
||||
//
|
||||
#ifndef HZ_USE_LIBDEBUG
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <algorithm> // std::min, std::max
|
||||
|
||||
#include "hz/scoped_ptr.h"
|
||||
#include "hz/down_cast.h"
|
||||
#include "hz/string_num.h" // number_to_string
|
||||
#include "hz/string_sprintf.h" // string_sprintf
|
||||
#include "hz/string_algo.h" // string_join
|
||||
@@ -113,7 +112,7 @@ namespace {
|
||||
Gtk::TreeModelColumn<const StorageProperty*> storage_column)
|
||||
{
|
||||
const StorageProperty* p = (*iter)[storage_column];
|
||||
Gtk::CellRendererText* crt = hz::down_cast<Gtk::CellRendererText*>(cr);
|
||||
Gtk::CellRendererText* crt = dynamic_cast<Gtk::CellRendererText*>(cr);
|
||||
if (crt) {
|
||||
std::string fg, bg;
|
||||
if (app_property_get_row_highlight_colors(p->warning, fg, bg)) {
|
||||
@@ -141,7 +140,7 @@ namespace {
|
||||
inline void app_highlight_tab_label(Gtk::Widget* label_widget,
|
||||
StorageProperty::warning_t warning, const Glib::ustring& original_label)
|
||||
{
|
||||
Gtk::Label* label = hz::down_cast<Gtk::Label*>(label_widget);
|
||||
Gtk::Label* label = dynamic_cast<Gtk::Label*>(label_widget);
|
||||
if (!label)
|
||||
return;
|
||||
|
||||
@@ -607,7 +606,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
num_tree_cols = app_gtkmm_create_tree_view_column(col_name, *treeview,
|
||||
"Name", "Attribute name (this is deduced from ID by smartctl and may be incorrect, as it's highly vendor-specific)", true);
|
||||
treeview->set_search_column(col_name.index());
|
||||
Gtk::CellRendererText* cr_name = hz::down_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
Gtk::CellRendererText* cr_name = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
if (cr_name)
|
||||
cr_name->property_weight() = Pango::WEIGHT_BOLD;
|
||||
|
||||
@@ -752,7 +751,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
num_tree_cols = app_gtkmm_create_tree_view_column(col_description, *treeview,
|
||||
"Description", "Entry description", true);
|
||||
treeview->set_search_column(col_description.index());
|
||||
// Gtk::CellRendererText* cr_name = hz::down_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
// Gtk::CellRendererText* cr_name = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
// if (cr_name)
|
||||
// cr_name->property_weight() = Pango::WEIGHT_BOLD ;
|
||||
|
||||
@@ -951,7 +950,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
model_columns.add(col_num); // we can use the column variable by value after this.
|
||||
num_tree_cols = app_gtkmm_create_tree_view_column(col_num, *treeview,
|
||||
"Test #", "Test # (greater may mean newer or older depending on drive model)", true);
|
||||
Gtk::CellRendererText* cr_test_num = hz::down_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
Gtk::CellRendererText* cr_test_num = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
if (cr_test_num)
|
||||
cr_test_num->property_weight() = Pango::WEIGHT_BOLD ;
|
||||
|
||||
@@ -1065,7 +1064,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
model_columns.add(col_num); // we can use the column variable by value after this.
|
||||
num_tree_cols = app_gtkmm_create_tree_view_column(col_num, *treeview,
|
||||
"Error #", "Error # in the error log (greater means newer)", true);
|
||||
Gtk::CellRendererText* cr_name = hz::down_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
Gtk::CellRendererText* cr_name = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
if (cr_name)
|
||||
cr_name->property_weight() = Pango::WEIGHT_BOLD ;
|
||||
|
||||
@@ -1290,7 +1289,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
model_columns.add(col_name);
|
||||
num_tree_cols = app_gtkmm_create_tree_view_column(col_name, *treeview, "Name", "Name", true);
|
||||
treeview->set_search_column(col_name.index());
|
||||
Gtk::CellRendererText* cr_name = hz::down_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
Gtk::CellRendererText* cr_name = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
|
||||
if (cr_name)
|
||||
cr_name->property_weight() = Pango::WEIGHT_BOLD ;
|
||||
|
||||
|
||||
@@ -538,12 +538,12 @@ void GscMainWindow::on_action_activated(GscMainWindow::action_t action_type)
|
||||
break;
|
||||
|
||||
case action_enable_smart: // this may be invoked on menu manipulation
|
||||
on_action_enable_smart_toggled(hz::down_cast<Gtk::ToggleAction*>(
|
||||
on_action_enable_smart_toggled(dynamic_cast<Gtk::ToggleAction*>(
|
||||
actiongroup_device->get_action(APP_ACTION_NAME(action_enable_smart)).operator->()));
|
||||
break;
|
||||
|
||||
case action_enable_aodc: // this may be invoked on menu manipulation
|
||||
on_action_enable_aodc_toggled(hz::down_cast<Gtk::ToggleAction*>(
|
||||
on_action_enable_aodc_toggled(dynamic_cast<Gtk::ToggleAction*>(
|
||||
actiongroup_device->get_action(APP_ACTION_NAME(action_enable_aodc)).operator->()));
|
||||
break;
|
||||
|
||||
@@ -815,9 +815,9 @@ Gtk::Menu* GscMainWindow::get_popup_menu(StorageDeviceRefPtr drive)
|
||||
if (!ui_manager)
|
||||
return 0;
|
||||
if (drive) {
|
||||
return hz::down_cast<Gtk::Menu*>(ui_manager->get_widget("/device_popup"));
|
||||
return dynamic_cast<Gtk::Menu*>(ui_manager->get_widget("/device_popup"));
|
||||
}
|
||||
return hz::down_cast<Gtk::Menu*>(ui_manager->get_widget("/empty_area_popup"));
|
||||
return dynamic_cast<Gtk::Menu*>(ui_manager->get_widget("/empty_area_popup"));
|
||||
}
|
||||
|
||||
|
||||
@@ -875,7 +875,7 @@ void GscMainWindow::set_drive_menu_status(StorageDeviceRefPtr drive)
|
||||
|
||||
// smart toggle status
|
||||
{
|
||||
Gtk::ToggleAction* action = hz::down_cast<Gtk::ToggleAction*>(
|
||||
Gtk::ToggleAction* action = dynamic_cast<Gtk::ToggleAction*>(
|
||||
actiongroup_device->get_action(APP_ACTION_NAME(action_enable_smart)).operator->());
|
||||
if (action) {
|
||||
action->set_active(smart_status == StorageDevice::status_enabled);
|
||||
@@ -885,13 +885,13 @@ void GscMainWindow::set_drive_menu_status(StorageDeviceRefPtr drive)
|
||||
|
||||
// aodc toggle status
|
||||
{
|
||||
Gtk::ToggleAction* action = hz::down_cast<Gtk::ToggleAction*>(
|
||||
Gtk::ToggleAction* action = dynamic_cast<Gtk::ToggleAction*>(
|
||||
actiongroup_device->get_action(APP_ACTION_NAME(action_enable_aodc)).operator->());
|
||||
|
||||
if (action) {
|
||||
Gtk::CheckMenuItem* dev_odc_item = hz::down_cast<Gtk::CheckMenuItem*>(ui_manager->get_widget(
|
||||
Gtk::CheckMenuItem* dev_odc_item = dynamic_cast<Gtk::CheckMenuItem*>(ui_manager->get_widget(
|
||||
"/main_menubar/device_menu/" APP_ACTION_NAME(action_enable_aodc)));
|
||||
Gtk::CheckMenuItem* popup_odc_item = hz::down_cast<Gtk::CheckMenuItem*>(ui_manager->get_widget(
|
||||
Gtk::CheckMenuItem* popup_odc_item = dynamic_cast<Gtk::CheckMenuItem*>(ui_manager->get_widget(
|
||||
"/device_popup/" APP_ACTION_NAME(action_enable_aodc)));
|
||||
Gtk::CheckButton* status_aodc_check = lookup_widget<Gtk::CheckButton*>("status_aodc_enabled_check");
|
||||
|
||||
|
||||
@@ -3,21 +3,19 @@ METASOURCES = AUTO
|
||||
|
||||
noinst_HEADERS = any_convert.h any_type.h any_type_holder.h ascii.h \
|
||||
bad_cast_exception.h bin2ascii_encoder.h common_types.h cstdint.h cstdint_impl_msvc.h \
|
||||
data_file.h debug.h down_cast.h env_tools.h errno_string.h error.h error_holder.h \
|
||||
exceptions.h format_unit.h fs_common.h fs_dir.h fs_dir_platform.h fs_error_holder.h \
|
||||
data_file.h debug.h env_tools.h errno_string.h error.h error_holder.h \
|
||||
format_unit.h fs_common.h fs_dir.h fs_dir_platform.h fs_error_holder.h \
|
||||
fs_file.h fs_path.h fs_path_utils.h fs_tools.h hz_config.h i18n.h \
|
||||
instance_manager.h intrusive_ptr.h intrusive_scoped_lock.h launch_url.h local_algo.h \
|
||||
locale_tools.h noncopyable.h optional_value.h portable_snprintf.h process_signal.h \
|
||||
ptr_container.h res_data.h scoped_array.h scoped_ptr.h static_assert.h stream_cast.h \
|
||||
ptr_container.h res_data.h scoped_array.h scoped_ptr.h stream_cast.h \
|
||||
string_algo.h string_num.h string_sprintf.h string_sprintf_macros.h string_wcmatch.h sync.h \
|
||||
sync_lock_ptr.h sync_multilock.h sync_part_get_policy.h sync_policy_boost.h \
|
||||
sync_policy_glib.h sync_policy_glibmm.h sync_policy_poco.h sync_policy_pthread.h \
|
||||
sync_policy_win32.h system_specific.h tls.h tls_policy_boost.h tls_policy_glib.h \
|
||||
tls_policy_pthread.h tls_policy_win32.h type_categories.h type_properties.h win32_tools.h
|
||||
sync_lock_ptr.h sync_multilock.h sync_part_get_policy.h \
|
||||
sync_policy_glib.h sync_policy_glibmm.h sync_policy_pthread.h \
|
||||
sync_policy_win32.h system_specific.h type_categories.h type_properties.h win32_tools.h
|
||||
|
||||
any_type_test_SOURCES = any_type_test.cpp
|
||||
bin2ascii_encoder_test_SOURCES = bin2ascii_encoder_test.cpp
|
||||
down_cast_test_SOURCES = down_cast_test.cpp
|
||||
errno_string_test_SOURCES = errno_string_test.cpp
|
||||
format_unit_test_SOURCES = format_unit_test.cpp
|
||||
fs_dir_test_SOURCES = fs_dir_test.cpp
|
||||
@@ -28,15 +26,14 @@ string_num_test_SOURCES = string_num_test.cpp
|
||||
string_wcmatch_test_SOURCES = string_wcmatch_test.cpp
|
||||
sync_test_SOURCES = sync_test.cpp
|
||||
sync_multilock_test_SOURCES = sync_multilock_test.cpp
|
||||
tls_test_SOURCES = tls_test.cpp
|
||||
|
||||
|
||||
# we don't list them in a separate variable because otherwise kdevelop won't see them.
|
||||
noinst_PROGRAMS =
|
||||
if ENABLE_TESTS
|
||||
noinst_PROGRAMS += any_type_test bin2ascii_encoder_test down_cast_test errno_string_test \
|
||||
noinst_PROGRAMS += any_type_test bin2ascii_encoder_test errno_string_test \
|
||||
format_unit_test fs_dir_test fs_file_test fs_path_test string_algo_test string_num_test \
|
||||
string_wcmatch_test sync_test sync_multilock_test tls_test
|
||||
string_wcmatch_test sync_test sync_multilock_test
|
||||
endif
|
||||
|
||||
tests: $(noinst_PROGRAMS)
|
||||
|
||||
@@ -127,21 +127,6 @@ struct any_convertible<From, From> : public AnyConvertibleValue<true> { };
|
||||
}
|
||||
|
||||
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
#define DEFINE_ANY_CONVERT_SPEC_STATIC_LLI(from_type) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, long long int)
|
||||
#else
|
||||
#define DEFINE_ANY_CONVERT_SPEC_STATIC_LLI(from_type)
|
||||
#endif
|
||||
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
#define DEFINE_ANY_CONVERT_SPEC_STATIC_ULLI(from_type) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned long long int)
|
||||
#else
|
||||
#define DEFINE_ANY_CONVERT_SPEC_STATIC_ULLI(from_type)
|
||||
#endif
|
||||
|
||||
|
||||
/// Define \c any_convertible and \c any_convert specializations for all built-in types as \c To.
|
||||
#define DEFINE_ANY_CONVERT_SPEC_ALL(from_type) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC_TOBOOL(from_type) \
|
||||
@@ -155,8 +140,8 @@ struct any_convertible<From, From> : public AnyConvertibleValue<true> { };
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned int) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, long int) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned long int) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC_LLI(from_type) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC_ULLI(from_type) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, long long int) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned long long int) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, double) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, float) \
|
||||
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, long double) \
|
||||
@@ -178,12 +163,8 @@ DEFINE_ANY_CONVERT_SPEC_ALL(int)
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned int)
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(long int)
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned long int)
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(long long int)
|
||||
#endif
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned long long int)
|
||||
#endif
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(long long int)
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned long long int)
|
||||
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(double)
|
||||
DEFINE_ANY_CONVERT_SPEC_ALL(float)
|
||||
|
||||
@@ -37,18 +37,12 @@ Original notes and copyright info follow:
|
||||
|
||||
|
||||
// Compilation options:
|
||||
// - Define DISABLE_RTTI=1 to disable RTTI checks and typeinfo-getter
|
||||
// functions. NOT recommended.
|
||||
|
||||
// - Define DISABLE_ANY_CONVERT=1 to disable all .convert functions
|
||||
// (avoids dependency on any_convert.h)
|
||||
*/
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
#include <typeinfo> // std::type_info
|
||||
#endif
|
||||
|
||||
#include <typeinfo> // std::type_info
|
||||
#include <iosfwd> // std::ostream
|
||||
#include <string> // to enable std::string printing. <string> is included already from any_type_holder.h.
|
||||
|
||||
@@ -107,7 +101,6 @@ class any_type {
|
||||
}
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
/// Get type info of the wrapped variable
|
||||
const std::type_info& type() const
|
||||
{
|
||||
@@ -118,7 +111,6 @@ class any_type {
|
||||
/// Check whether the wrapped variable is of type T.
|
||||
template<typename T> inline
|
||||
bool is_type() const; // e.g. is_type<int>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -248,9 +240,7 @@ ValueType any_cast(any_type* operand)
|
||||
typedef typename type_remove_pointer<ValueType>::type nopointer;
|
||||
|
||||
if (operand && operand->content
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
&& operand->type() == typeid(nopointer)
|
||||
#endif
|
||||
) {
|
||||
return &static_cast<internal::AnyHolder<nopointer>*>(operand->content)->value;
|
||||
}
|
||||
@@ -276,12 +266,10 @@ ValueType any_cast(any_type& operand)
|
||||
typedef typename type_remove_reference<ValueType>::type nonref;
|
||||
|
||||
if (!operand.content)
|
||||
THROW_CUSTOM_BAD_CAST(bad_any_cast, operand.type(), typeid(nonref));
|
||||
throw bad_any_cast(operand.type(), typeid(nonref));
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
if (operand.type() != typeid(nonref))
|
||||
THROW_CUSTOM_BAD_CAST(bad_any_cast, operand.type(), typeid(nonref));
|
||||
#endif
|
||||
throw bad_any_cast(operand.type(), typeid(nonref));
|
||||
|
||||
return static_cast<internal::AnyHolder<nonref>*>(operand.content)->value;
|
||||
}
|
||||
@@ -294,12 +282,10 @@ ValueType any_cast(const any_type& operand)
|
||||
typedef typename type_remove_reference<ValueType>::type nonref;
|
||||
|
||||
if (!operand.content)
|
||||
THROW_CUSTOM_BAD_CAST(bad_any_cast, operand.type(), typeid(nonref));
|
||||
throw bad_any_cast(operand.type(), typeid(nonref));
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
if (operand.type() != typeid(nonref))
|
||||
THROW_CUSTOM_BAD_CAST(bad_any_cast, operand.type(), typeid(nonref));
|
||||
#endif
|
||||
throw bad_any_cast(operand.type(), typeid(nonref));
|
||||
|
||||
return static_cast<const internal::AnyHolder<nonref>*>(operand.content)->value;
|
||||
}
|
||||
@@ -320,8 +306,6 @@ inline any_type& any_type::swap(any_type& rhs)
|
||||
}
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
|
||||
template<typename T> inline
|
||||
bool any_type::is_type() const
|
||||
{
|
||||
@@ -329,8 +313,6 @@ bool any_type::is_type() const
|
||||
return static_cast<bool>(any_cast<T*>(this));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T> inline
|
||||
bool any_type::get(T& put_it_here) const
|
||||
@@ -366,7 +348,7 @@ T any_type::convert() const
|
||||
typedef typename type_remove_reference<T>::type nonref;
|
||||
nonref result;
|
||||
if (!this->convert(result))
|
||||
THROW_CUSTOM_BAD_CAST(bad_any_cast, this->type(), typeid(nonref));
|
||||
throw bad_any_cast(this->type(), typeid(nonref));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -21,10 +21,7 @@
|
||||
Internal header, do not include manually.
|
||||
*/
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
#include <typeinfo> // std::type_info
|
||||
#endif
|
||||
|
||||
#include <typeinfo> // std::type_info
|
||||
#include <iosfwd> // std::ostream
|
||||
#include <string>
|
||||
|
||||
@@ -48,10 +45,9 @@ struct AnyHolderBase {
|
||||
/// Virtual destructor
|
||||
virtual ~AnyHolderBase() { }
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
/// Get std::type_info for the wrapped variable
|
||||
virtual const std::type_info& type() const = 0;
|
||||
#endif
|
||||
|
||||
/// Clone the wrapped variable
|
||||
virtual AnyHolderBase* clone() const = 0;
|
||||
|
||||
@@ -75,12 +71,8 @@ struct AnyHolderBase {
|
||||
virtual bool convert(unsigned int& val) const = 0;
|
||||
virtual bool convert(long int& val) const = 0;
|
||||
virtual bool convert(unsigned long int& val) const = 0;
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
virtual bool convert(long long int& val) const = 0;
|
||||
#endif
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
virtual bool convert(unsigned long long int& val) const = 0;
|
||||
#endif
|
||||
|
||||
virtual bool convert(double& val) const = 0;
|
||||
virtual bool convert(float& val) const = 0;
|
||||
@@ -109,13 +101,11 @@ struct AnyHolder : public AnyHolderBase {
|
||||
{ }
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
/// Get std::type_info object for the wrapped variable
|
||||
const std::type_info& type() const
|
||||
{
|
||||
return typeid(ValueType);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Clone the wrapped variable. Note that this is not a deep clone.
|
||||
AnyHolderBase* clone() const
|
||||
@@ -147,12 +137,8 @@ struct AnyHolder : public AnyHolderBase {
|
||||
bool convert(unsigned int& val) const { return any_convert(value, val); }
|
||||
bool convert(long int& val) const { return any_convert(value, val); }
|
||||
bool convert(unsigned long int& val) const { return any_convert(value, val); }
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
bool convert(long long int& val) const { return any_convert(value, val); }
|
||||
#endif
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
bool convert(unsigned long long int& val) const { return any_convert(value, val); }
|
||||
#endif
|
||||
|
||||
bool convert(double& val) const { return any_convert(value, val); }
|
||||
bool convert(float& val) const { return any_convert(value, val); }
|
||||
|
||||
@@ -80,15 +80,9 @@ struct TestClass {
|
||||
|
||||
a.get<std::string>();
|
||||
|
||||
// is_type<> is available only with RTTI
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
if (a.is_type<std::string>())
|
||||
return any_cast<std::string>(a);
|
||||
return std::string();
|
||||
|
||||
#else // can't do any checking here
|
||||
return any_cast<std::string>(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
(C) 2008 - 2017 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
@@ -14,15 +14,10 @@
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
// we need these for instantiation, even if exceptions are disabled.
|
||||
#include <exception> // std::exception
|
||||
#include <string>
|
||||
#include <typeinfo> // std::type_info
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
#include <typeinfo> // std::type_info
|
||||
#endif
|
||||
|
||||
#include "exceptions.h" // THROW_FATAL
|
||||
#include "system_specific.h" // type_name_demangle
|
||||
#include "string_sprintf.h" // hz::string_sprintf
|
||||
|
||||
@@ -32,9 +27,6 @@ namespace hz {
|
||||
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
|
||||
|
||||
/// Children of this class are thrown from various casting functions
|
||||
class bad_cast_except : virtual public std::exception { // from <exception>
|
||||
public:
|
||||
@@ -93,45 +85,6 @@ class bad_cast_except : virtual public std::exception { // from <exception>
|
||||
};
|
||||
|
||||
|
||||
#else // no RTTI variant:
|
||||
|
||||
|
||||
/// Children of this class are thrown from various casting functions
|
||||
class bad_cast_except : virtual public std::exception { // from <exception>
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
/// \param self_name child class name
|
||||
/// \param error_msg error message
|
||||
bad_cast_except(const char* self_name = 0, const char* error_msg = 0)
|
||||
: self_name_(self_name ? self_name : "bad_cast_except"),
|
||||
error_msg_(error_msg ? error_msg : "Type cast failed.")
|
||||
{ }
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~bad_cast_except() throw()
|
||||
{ }
|
||||
|
||||
/// Reimplemented from std::exception
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return (msg_ = (self_name_.empty() ? "[unknown]" : self_name_) + ": " + error_msg_).c_str();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
mutable std::string msg_; ///< This must be a member to avoid its destruction on function call return. use what().
|
||||
|
||||
std::string self_name_; ///< The exception class name
|
||||
std::string error_msg_; ///< Error message
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
@@ -145,11 +98,9 @@ class custom_cast_exception : public hz::bad_cast_except {
|
||||
custom_cast_exception() : hz::bad_cast_except("custom_cast_exception", "Cast failed from %s to %s.")
|
||||
{ }
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
custom_cast_exception(const std::type_info& src, const std::type_info& dest)
|
||||
: hz::bad_cast_except(src, dest, "custom_cast_exception", "Cast failed")
|
||||
{ }
|
||||
#endif
|
||||
};
|
||||
*/
|
||||
|
||||
@@ -159,8 +110,6 @@ class custom_cast_exception : public hz::bad_cast_except {
|
||||
/// and shows \c rtti_msg if RTTI is enabled and nortti_msg if RTTI is disabled.
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
|
||||
#define DEFINE_BAD_CAST_EXCEPTION(name, rtti_msg, nortti_msg) \
|
||||
class name : public hz::bad_cast_except { \
|
||||
public: \
|
||||
@@ -171,35 +120,6 @@ class custom_cast_exception : public hz::bad_cast_except {
|
||||
{ } \
|
||||
}
|
||||
|
||||
#else // no rtti:
|
||||
|
||||
#define DEFINE_BAD_CAST_EXCEPTION(name, rtti_msg, nortti_msg) \
|
||||
class name : public hz::bad_cast_except { \
|
||||
public: \
|
||||
name() : hz::bad_cast_except(#name, nortti_msg) \
|
||||
{ } \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// \def THROW_CUSTOM_BAD_CAST(name, from, to)
|
||||
/// Throw a bad cast exception of class \c name, with \c from
|
||||
/// and \c to being std::type_info class objects.
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
|
||||
#define THROW_CUSTOM_BAD_CAST(name, from, to) \
|
||||
THROW_FATAL(name(from, to))
|
||||
|
||||
#else // no rtti:
|
||||
|
||||
#define THROW_CUSTOM_BAD_CAST(name, from, to) \
|
||||
THROW_FATAL(name())
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -212,15 +212,7 @@ anyway).
|
||||
|
||||
#define DBG_FILE __FILE__
|
||||
#define DBG_LINE __LINE__
|
||||
|
||||
|
||||
#if defined HAVE_CXX___func__ && HAVE_CXX___func__
|
||||
#define DBG_FUNC_NAME __func__
|
||||
#elif defined HAVE_CXX___FUNCTION__ && HAVE_CXX___FUNCTION__
|
||||
#define DBG_FUNC_NAME __FUNCTION__
|
||||
#else
|
||||
#define DBG_FUNC_NAME "unknown"
|
||||
#endif
|
||||
#define DBG_FUNC_NAME __func__
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DBG_FUNC_PRNAME __PRETTY_FUNCTION__
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2003 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz
|
||||
/// \weakgroup hz
|
||||
/// @{
|
||||
|
||||
#ifndef HZ_DOWN_CAST_H
|
||||
#define HZ_DOWN_CAST_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#include "static_assert.h" // HZ_STATIC_ASSERT
|
||||
#include "type_properties.h" // type_is_polymorphic, type_is_pointer, type_remove_pointer
|
||||
|
||||
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
/// Perform a down cast (pointers only!).
|
||||
/// This cast works with polymorphic and non-polymorphic types.
|
||||
/// If RTTI is disabled, it will revert to static_cast; otherwise,
|
||||
/// dynamic_cast is used for polymorphic types and static_cast
|
||||
/// for non-polymorphic types.
|
||||
template<typename Target, typename Source> inline
|
||||
Target down_cast(const Source& arg);
|
||||
|
||||
|
||||
|
||||
#if defined DISABLE_RTTI && DISABLE_RTTI
|
||||
|
||||
|
||||
template<typename Target, typename Source> inline
|
||||
Target down_cast(const Source& arg)
|
||||
{
|
||||
// accept pointers only:
|
||||
HZ_STATIC_ASSERT(type_is_pointer<Target>::value && type_is_pointer<Source>::value, not_a_pointer);
|
||||
|
||||
return static_cast<Target>(arg);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
|
||||
namespace internal {
|
||||
|
||||
/// Helper for down_cast, uses dynamic_cast unless the types are non-polymorphic,
|
||||
/// in which case static_cast is used.
|
||||
template<typename Target, typename Source,
|
||||
bool Polymorphic = type_is_polymorphic<typename type_remove_pointer<Target>::type>::value
|
||||
&& type_is_polymorphic<typename type_remove_pointer<Source>::type>::value >
|
||||
struct down_cast_helper
|
||||
{
|
||||
static Target func(const Source& arg)
|
||||
{
|
||||
return dynamic_cast<Target>(arg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Non-polymorphic specialization
|
||||
template<typename Target, typename Source>
|
||||
struct down_cast_helper<Target, Source, false>
|
||||
{
|
||||
static Target func(const Source& arg)
|
||||
{
|
||||
return static_cast<Target>(arg);
|
||||
}
|
||||
};
|
||||
|
||||
} // ns internal
|
||||
|
||||
|
||||
|
||||
template<typename Target, typename Source> inline
|
||||
Target down_cast(const Source& arg)
|
||||
{
|
||||
// accept pointers only:
|
||||
HZ_STATIC_ASSERT(type_is_pointer<Target>::value && type_is_pointer<Source>::value, not_a_pointer);
|
||||
|
||||
return internal::down_cast_helper<Target, Source>::func(arg);
|
||||
}
|
||||
|
||||
|
||||
#endif // DISABLE_RTTI
|
||||
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -1,100 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_unlicense.txt
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz_tests
|
||||
/// \weakgroup hz_tests
|
||||
/// @{
|
||||
|
||||
// disable libdebug, we don't link to it
|
||||
#undef HZ_USE_LIBDEBUG
|
||||
#define HZ_USE_LIBDEBUG 0
|
||||
// enable libdebug emulation through std::cerr
|
||||
#undef HZ_EMULATE_LIBDEBUG
|
||||
#define HZ_EMULATE_LIBDEBUG 1
|
||||
|
||||
|
||||
|
||||
// #define DISABLE_RTTI
|
||||
|
||||
|
||||
// The first header should be then one we're testing, to avoid missing
|
||||
// header pitfalls.
|
||||
#include "down_cast.h"
|
||||
|
||||
// #include <iostream>
|
||||
|
||||
|
||||
|
||||
struct TestBase { };
|
||||
|
||||
struct TestChild : public TestBase { };
|
||||
|
||||
struct TestPoly : public TestBase
|
||||
{
|
||||
virtual ~TestPoly() { }
|
||||
};
|
||||
|
||||
struct TestPoly2 : public TestPoly
|
||||
{
|
||||
virtual ~TestPoly2() { }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// Main function for the test
|
||||
int main()
|
||||
{
|
||||
// std::cerr << "TestBase: " << hz::type_is_polymorphic<TestBase>::value << "\n";
|
||||
// std::cerr << "TestChild: " << hz::type_is_polymorphic<TestChild>::value << "\n";
|
||||
// std::cerr << "TestPoly: " << hz::type_is_polymorphic<TestPoly>::value << "\n";
|
||||
|
||||
|
||||
{
|
||||
TestChild c;
|
||||
TestBase* b = &c;
|
||||
|
||||
hz::down_cast<TestChild*>(b); // should use static_cast (both are non-polymorphic)
|
||||
// static_cast<TestChild*>(b);
|
||||
}
|
||||
|
||||
{
|
||||
TestPoly p;
|
||||
TestBase* b = &p;
|
||||
|
||||
hz::down_cast<TestPoly*>(b); // should use static_cast (base is non-polymorphic)
|
||||
// static_cast<TestChild*>(b);
|
||||
}
|
||||
|
||||
{
|
||||
TestPoly2 p;
|
||||
TestPoly* b = &p;
|
||||
|
||||
hz::down_cast<TestPoly2*>(b); // should use dynamic_cast (both are polymorphic)
|
||||
// dynamic_cast<TestPoly2*>(b);
|
||||
// static_cast<TestPoly2*>(b);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
TestPoly p;
|
||||
TestBase& b = p;
|
||||
|
||||
hz::down_cast<TestPoly&>(b); // should throw an error, only pointers are supported.
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// @}
|
||||
@@ -16,14 +16,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <exception> // for std::exception specialization
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
#include <typeinfo> // std::type_info
|
||||
#endif
|
||||
|
||||
// #if defined ENABLE_GLIBMM && ENABLE_GLIBMM
|
||||
// # include <glibmm/error.h> // for Glib::Error specialization
|
||||
// #endif
|
||||
#include <typeinfo> // std::type_info
|
||||
|
||||
#include "debug.h" // DBG_ASSERT
|
||||
#include "errno_string.h" // hz::errno_string
|
||||
@@ -33,17 +26,6 @@
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\file
|
||||
Compilation options:
|
||||
- Define DISABLE_RTTI to disable RTTI checks and typeinfo-getter
|
||||
functions. NOT recommended.
|
||||
- Define ENABLE_GLIBMM to 1 to enable glibmm-related code (mainly
|
||||
utf8 string messages and Glib::Error specialization). Note that this
|
||||
will also enable GLIB.
|
||||
*/
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
@@ -103,20 +85,16 @@ class ErrorBase {
|
||||
virtual ErrorBase* clone() = 0; // needed for copying by base pointers
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
/// Get std::type_info for the error code type.
|
||||
virtual const std::type_info& get_code_type() const = 0;
|
||||
#endif
|
||||
|
||||
|
||||
/// Get error code of type \c CodeMemberType
|
||||
template<class CodeMemberType>
|
||||
CodeMemberType get_code() const // this may throw on bad cast!
|
||||
{
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
if (get_code_type() != typeid(CodeMemberType))
|
||||
THROW_CUSTOM_BAD_CAST(type_mismatch, get_code_type(), typeid(CodeMemberType));
|
||||
#endif
|
||||
throw type_mismatch(get_code_type(), typeid(CodeMemberType));
|
||||
return static_cast<const Error<CodeMemberType>*>(this)->code;
|
||||
}
|
||||
|
||||
@@ -124,10 +102,8 @@ class ErrorBase {
|
||||
template<class CodeMemberType>
|
||||
bool get_code(CodeMemberType& put_it_here) const // this doesn't throw
|
||||
{
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
if (get_code_type() != typeid(CodeMemberType))
|
||||
return false;
|
||||
#endif
|
||||
put_it_here = static_cast<const Error<CodeMemberType>*>(this)->code;
|
||||
return true;
|
||||
}
|
||||
@@ -175,7 +151,7 @@ class ErrorBase {
|
||||
protected:
|
||||
|
||||
std::string type; ///< Error type
|
||||
level_t level; ///< Error severity
|
||||
level_t level = ErrorLevel::none; ///< Error severity
|
||||
std::string message; ///< Error message
|
||||
|
||||
};
|
||||
@@ -202,12 +178,10 @@ class ErrorCodeHolder : public ErrorBase {
|
||||
|
||||
public:
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
// Reimplemented from ErrorBase
|
||||
const std::type_info& get_code_type() const { return typeid(CodeType); }
|
||||
#endif
|
||||
|
||||
CodeType code; ///< Error code. We have a class specialization for references too
|
||||
CodeType code = CodeType(); ///< Error code. We have a class specialization for references too
|
||||
|
||||
};
|
||||
|
||||
@@ -225,10 +199,8 @@ class ErrorCodeHolder<void> : public ErrorBase {
|
||||
|
||||
public:
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
// Reimplemented from ErrorBase
|
||||
const std::type_info& get_code_type() const { return typeid(void); }
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz
|
||||
/// \weakgroup hz
|
||||
/// @{
|
||||
|
||||
#ifndef HZ_EXCEPTIONS_H
|
||||
#define HZ_EXCEPTIONS_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
// These headers may be needed for object creation even if exceptions are disabled.
|
||||
// #include <exception> // std::exception
|
||||
// #include <stdexcept> // standard exceptions, derived from std::exception
|
||||
|
||||
|
||||
/**
|
||||
Define DISABLE_EXCEPTIONS=1 to disable exception use
|
||||
(only applicable when using the macros defined below).
|
||||
Useful for e.g. gcc's -fno-exceptions, etc...
|
||||
*/
|
||||
|
||||
/// \def THROW_FATAL(ex)
|
||||
/// If you use -fno-exceptions gcc switch (or similar), define
|
||||
/// DISABLE_EXCEPTIONS and no throw statement will occur if
|
||||
/// you use THROW_FATAL instead of throw (calling this will cause abort()
|
||||
/// after printing an error message to stderr).
|
||||
/// Otherwise, it's equivalent to a simple <tt>throw ex</tt>.
|
||||
/// Note: The exceptions MUST have a what() member function for this to work.
|
||||
/// Do NOT put ex into parentheses. gcc-3.3 gives syntax errors about that (huh?).
|
||||
|
||||
/// \def THROW_WARN(ex)
|
||||
/// Same as THROW_FATAL(ex), but no abort() in case of no-exceptions.
|
||||
|
||||
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
|
||||
#define THROW_FATAL(ex) \
|
||||
throw ex
|
||||
|
||||
#define THROW_WARN(ex) \
|
||||
throw ex
|
||||
|
||||
|
||||
#else // no-exceptions alternative:
|
||||
|
||||
|
||||
#include <cstdlib> // std::abort()
|
||||
#include <cstdio> // std::fprintf
|
||||
// #include <iostream> // std::cerr
|
||||
|
||||
// We could use std::exit(EXIT_FAILURE), but it's somewhat inconsistent
|
||||
// in regards of stack unwinding and destructors, so use abort()
|
||||
// std::cerr << "Fatal exception thrown (exceptions are disabled): " << ex.what() << std::endl;
|
||||
#define THROW_FATAL(ex) \
|
||||
if (true) { \
|
||||
const char* ex_what = ex.what(); \
|
||||
std::fprintf(stderr, "Fatal exception thrown (exceptions are disabled): %s\n", ex_what ? ex_what : "[unknown]"); \
|
||||
std::abort(); \
|
||||
} else (void)0
|
||||
|
||||
// std::cerr << "Warn exception thrown (exceptions are disabled): " << ex.what() << std::endl;
|
||||
#define THROW_WARN(ex) \
|
||||
if (true) { \
|
||||
std::fprintf(stderr, "Warn exception thrown (exceptions are disabled): %s\n", ex_what ? ex_what : "[unknown]"); \
|
||||
} else (void)0
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -80,30 +80,6 @@ HZ library internal implementation helpers.
|
||||
|
||||
|
||||
|
||||
/// \def DISABLE_RTTI
|
||||
/// Defined to 0 or 1. If 1, RTTI is disabled.
|
||||
#ifndef DISABLE_RTTI
|
||||
// No auto-detection here...
|
||||
// There's __GXX_RTTI (not used here; since gcc >= 4.3 (?)), but I'm not sure if it's valid.
|
||||
#define DISABLE_RTTI 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// \def DISABLE_EXCEPTIONS
|
||||
/// Defined to 0 or 1. If 1, exceptions are disabled.
|
||||
#ifndef DISABLE_EXCEPTIONS
|
||||
// some auto-detection (gcc 3.3 or later (I think))
|
||||
#if defined __GNUC__ && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && !defined __EXCEPTIONS
|
||||
#define DISABLE_EXCEPTIONS 0
|
||||
#else
|
||||
#define DISABLE_EXCEPTIONS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// \def HAVE_CXX_EXTERN_C_OVERLOAD
|
||||
/// Defined to 0 or 1. If 1, compiler supports overloading on extern "C" function pointer arguments.
|
||||
#ifndef HAVE_CXX_EXTERN_C_OVERLOAD
|
||||
@@ -143,32 +119,6 @@ HZ library internal implementation helpers.
|
||||
|
||||
|
||||
|
||||
/// \def HAVE_CXX___func__
|
||||
/// Defined to 0 or 1. If 1, compiler supports __func__.
|
||||
#ifndef HAVE_CXX___func__
|
||||
// this is a C99 thing, but I don't know of any other compiler which supports it
|
||||
#if defined __GNUC__
|
||||
#define HAVE_CXX___func__ 1
|
||||
#else
|
||||
#define HAVE_CXX___func__ 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/// \def HAVE_CXX___FUNCTION__
|
||||
/// Defined to 0 or 1. If 1, compiler supports __FUNCTION__.
|
||||
#ifndef HAVE_CXX___FUNCTION__
|
||||
// suncc supports this, but only with extensions enabled (can we check those?)
|
||||
#if defined __GNUC__ || defined _MSC_VER
|
||||
#define HAVE_CXX___FUNCTION__ 1
|
||||
#else
|
||||
#define HAVE_CXX___FUNCTION__ 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// \def HAVE_WIN_SE_FUNCS
|
||||
/// Defined to 0 or 1. If 1, compiler supports Win32's "secure" *_s() functions (since msvc 2005/8.0).
|
||||
/// If some of the functions have different requirements, they are listed separately.
|
||||
|
||||
@@ -37,12 +37,7 @@ See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
|
||||
#include <cstring> // strncpy / strlen
|
||||
#include <exception> // std::exception
|
||||
// #include <iosfwd> // std::ostream (for operator<<)
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
#include <typeinfo> // std::type_info
|
||||
#endif
|
||||
|
||||
#include "exceptions.h" // THROW_FATAL
|
||||
#include <typeinfo> // std::type_info
|
||||
|
||||
|
||||
/// \def INTRUSIVE_PTR_TRACING
|
||||
@@ -81,15 +76,12 @@ struct intrusive_ptr_error : virtual public std::exception { // from <exception
|
||||
|
||||
/// Constructor
|
||||
intrusive_ptr_error(const char* msg)
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
: type_(typeid(void))
|
||||
#endif
|
||||
{
|
||||
std::size_t buf_len = std::strlen(msg) + 1;
|
||||
msg_ = std::strncpy(new char[buf_len], msg, buf_len);
|
||||
}
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
/// Constructor
|
||||
intrusive_ptr_error(const char* msg, const std::type_info& type)
|
||||
: msg_(0), type_(type)
|
||||
@@ -104,7 +96,6 @@ struct intrusive_ptr_error : virtual public std::exception { // from <exception
|
||||
std::strncpy(msg_ + msg_len, tmsg, tmsg_len);
|
||||
std::strncpy(msg_ + msg_len + tmsg_len, tname, tname_len + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~intrusive_ptr_error() throw()
|
||||
@@ -121,9 +112,7 @@ struct intrusive_ptr_error : virtual public std::exception { // from <exception
|
||||
}
|
||||
|
||||
char* msg_; ///< Error message
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
const std::type_info& type_; ///< Type information of the pointee
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -136,60 +125,28 @@ struct intrusive_ptr_error : virtual public std::exception { // from <exception
|
||||
/// additional information to std::cerr.
|
||||
|
||||
|
||||
#if defined INTRUSIVE_PTR_TRACING && INTRUSIVE_PTR_TRACING \
|
||||
&& defined INTRUSIVE_PTR_RUNTIME_CHECKS && INTRUSIVE_PTR_RUNTIME_CHECKS
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
if (cond) { \
|
||||
std::cerr << (msg) << " Type: " << type.name() << "\n"; \
|
||||
throw intrusive_ptr_error(msg, type); \
|
||||
}
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
#elif defined INTRUSIVE_PTR_TRACING && INTRUSIVE_PTR_TRACING
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
{ \
|
||||
std::cerr << (msg) << " Type: " << type.name() << "\n"; \
|
||||
}
|
||||
|
||||
#if defined INTRUSIVE_PTR_TRACING && INTRUSIVE_PTR_TRACING \
|
||||
&& defined INTRUSIVE_PTR_RUNTIME_CHECKS && INTRUSIVE_PTR_RUNTIME_CHECKS
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
if (cond) { \
|
||||
std::cerr << (msg) << " Type: " << type.name() << "\n"; \
|
||||
THROW_FATAL(intrusive_ptr_error(msg, type)); \
|
||||
}
|
||||
|
||||
#elif defined INTRUSIVE_PTR_TRACING && INTRUSIVE_PTR_TRACING
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
{ \
|
||||
std::cerr << (msg) << " Type: " << type.name() << "\n"; \
|
||||
}
|
||||
|
||||
#elif defined INTRUSIVE_PTR_RUNTIME_CHECKS && INTRUSIVE_PTR_RUNTIME_CHECKS
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
if (cond) { \
|
||||
THROW_FATAL(intrusive_ptr_error(msg, type)); \
|
||||
}
|
||||
|
||||
#else
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) { }
|
||||
#endif
|
||||
|
||||
|
||||
#else // no rtti
|
||||
|
||||
#if defined INTRUSIVE_PTR_TRACING && INTRUSIVE_PTR_TRACING \
|
||||
&& defined INTRUSIVE_PTR_RUNTIME_CHECKS && INTRUSIVE_PTR_RUNTIME_CHECKS
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
if (cond) { \
|
||||
std::cerr << (msg) << "\n"; \
|
||||
THROW_FATAL(intrusive_ptr_error(msg)); \
|
||||
}
|
||||
|
||||
#elif defined INTRUSIVE_PTR_TRACING && INTRUSIVE_PTR_TRACING
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
{ \
|
||||
std::cerr << (msg) << "\n"; \
|
||||
}
|
||||
|
||||
#elif defined INTRUSIVE_PTR_RUNTIME_CHECKS && INTRUSIVE_PTR_RUNTIME_CHECKS
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
if (cond) { \
|
||||
THROW_FATAL(intrusive_ptr_error(msg)); \
|
||||
}
|
||||
|
||||
#else
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) { }
|
||||
#endif
|
||||
#elif defined INTRUSIVE_PTR_RUNTIME_CHECKS && INTRUSIVE_PTR_RUNTIME_CHECKS
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) \
|
||||
if (cond) { \
|
||||
throw intrusive_ptr_error(msg, type); \
|
||||
}
|
||||
|
||||
#else
|
||||
#define INTRUSIVE_PTR_THROW(cond, type, msg) { }
|
||||
#endif
|
||||
|
||||
|
||||
@@ -641,9 +598,6 @@ intrusive_ptr<T, R> ptr_const_cast(const intrusive_ptr<U, S>& p)
|
||||
return const_cast<T*>(p.get());
|
||||
}
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
|
||||
/// Perform a dynamic cast on intrusive_ptr
|
||||
template<class T, class R, class U> inline
|
||||
intrusive_ptr<T> ptr_dynamic_cast(const intrusive_ptr<U, R>& p)
|
||||
@@ -651,8 +605,6 @@ intrusive_ptr<T> ptr_dynamic_cast(const intrusive_ptr<U, R>& p)
|
||||
return dynamic_cast<T*>(p.get());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Don't define this - it may conflict with actual intrusive_ptr<T, R> overloads
|
||||
|
||||
@@ -72,20 +72,16 @@ inline std::string locale_c_get()
|
||||
/// \return false on failure (no exception is thrown)
|
||||
inline bool locale_cpp_set(const std::locale& loc, std::locale& old_locale)
|
||||
{
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
try {
|
||||
#endif
|
||||
// under FreeBSD (at least 6.x) and OSX, this may throw on anything
|
||||
// except "C" and "POSIX" with message:
|
||||
// "locale::facet::_S_create_c_locale name not valid".
|
||||
// Blame inadequate implementations.
|
||||
old_locale = std::locale::global(loc);
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -96,16 +92,12 @@ inline bool locale_cpp_set(const std::locale& loc, std::locale& old_locale)
|
||||
/// \return false on failure (no exception is thrown)
|
||||
inline bool locale_cpp_set(const std::locale& loc, std::string& old_locale)
|
||||
{
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
try {
|
||||
#endif
|
||||
old_locale = std::locale::global(loc).name(); // not sure, but name() may not be unique (?)
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -116,16 +108,12 @@ inline bool locale_cpp_set(const std::locale& loc, std::string& old_locale)
|
||||
/// \return false on failure (no exception is thrown)
|
||||
inline bool locale_cpp_set(const std::locale& loc)
|
||||
{
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
try {
|
||||
#endif
|
||||
std::locale::global(loc);
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -136,16 +124,12 @@ inline bool locale_cpp_set(const std::locale& loc)
|
||||
/// \return false on failure (no exception is thrown)
|
||||
inline bool locale_cpp_set(const std::string& loc, std::locale& old_locale)
|
||||
{
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
try {
|
||||
#endif
|
||||
old_locale = std::locale::global(std::locale(loc.c_str()));
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -155,16 +139,12 @@ inline bool locale_cpp_set(const std::string& loc, std::locale& old_locale)
|
||||
/// \return false on failure (no exception is thrown)
|
||||
inline bool locale_cpp_set(const std::string& loc, std::string& old_locale)
|
||||
{
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
try {
|
||||
#endif
|
||||
old_locale = std::locale::global(std::locale(loc.c_str())).name(); // not sure, but name() may not be unique (?)
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -174,16 +154,12 @@ inline bool locale_cpp_set(const std::string& loc, std::string& old_locale)
|
||||
/// \return false on failure (no exception is thrown)
|
||||
inline bool locale_cpp_set(const std::string& loc)
|
||||
{
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
try {
|
||||
#endif
|
||||
std::locale::global(std::locale(loc.c_str()));
|
||||
#if !(defined DISABLE_EXCEPTIONS && DISABLE_EXCEPTIONS)
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#include "type_properties.h"
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ class ptr_container : public Container {
|
||||
{
|
||||
put_here.assign(this->begin(), this->end());
|
||||
for (typename ReturnedContainer::iterator i = put_here.begin(); i != put_here.end(); ++i) {
|
||||
*i = new typename hz::type_remove_pointer<value_type>::type(*i);
|
||||
*i = new typename std::remove_pointer_t<value_type>(*i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2003 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz
|
||||
/// \weakgroup hz
|
||||
/// @{
|
||||
|
||||
#ifndef HZ_STATIC_ASSERT_H
|
||||
#define HZ_STATIC_ASSERT_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
|
||||
/**
|
||||
\file
|
||||
Note: Please specify the hz namespace explicitly (i.e. hz::static_assertion<>)
|
||||
to avoid conflicts with various other implementations; Better yet,
|
||||
use HZ_STATIC_ASSERT macro.
|
||||
*/
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
/// Static assertion - similar to C++11's std::static_assert, but for C++98.
|
||||
template<bool B>
|
||||
struct static_assertion;
|
||||
|
||||
template<>
|
||||
struct static_assertion<true>
|
||||
{ };
|
||||
|
||||
|
||||
// Use this when making an explicit static_assertion<false>.
|
||||
// Without T, Intel C++ explicitly instantiates the static_assertion type.
|
||||
// Usage: HZ_STATIC_ASSERT(hz::static_false<T>::value, cannot_do_this);
|
||||
// where T is an instantiation-dependent type.
|
||||
template<typename T>
|
||||
struct static_false
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
/// Use this macro for static checks with messages.
|
||||
/// \c msg_identifier doesn't have to be defined as a C++ identifier,
|
||||
/// it's just a message that will appear in compiler error output.
|
||||
#define HZ_STATIC_ASSERT(cond, msg_identifier) \
|
||||
if (true) { \
|
||||
hz::static_assertion<((cond) != 0)> ERROR_##msg_identifier; \
|
||||
(void)ERROR_##msg_identifier; \
|
||||
} else (void)0
|
||||
|
||||
|
||||
// Maybe use typedef?
|
||||
|
||||
|
||||
// Alternate version:
|
||||
|
||||
/*
|
||||
namespace hz {
|
||||
template<bool B>
|
||||
struct STATIC_ASSERTION_FAILURE;
|
||||
|
||||
template<>
|
||||
struct STATIC_ASSERTION_FAILURE<true>
|
||||
{
|
||||
enum { value = 1 };
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct static_assertion_test
|
||||
{ };
|
||||
} // ns
|
||||
|
||||
#define HZ_STATIC_ASSERT(cond) \
|
||||
typedef hz::static_assertion_test<sizeof(hz::STATIC_ASSERTION_FAILURE<(bool)(cond)>)> \
|
||||
hz_static_assertion_ ## __LINE__
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -14,12 +14,7 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <limits> // std::numeric_limits
|
||||
|
||||
#if __cplusplus > 201100L
|
||||
#include <type_traits>
|
||||
#else
|
||||
#include "type_properties.h" // type_is_pointer
|
||||
#endif
|
||||
#include <type_traits>
|
||||
|
||||
#include "bad_cast_exception.h"
|
||||
|
||||
@@ -85,15 +80,9 @@ namespace internal {
|
||||
template<typename InputStreamable>
|
||||
bool operator>>(InputStreamable &output)
|
||||
{
|
||||
#if __cplusplus > 201100L
|
||||
return !std::is_pointer<InputStreamable>::value &&
|
||||
stream >> output &&
|
||||
stream.get() == std::char_traits<std::stringstream::char_type>::eof();
|
||||
#else
|
||||
return !hz::type_is_pointer<InputStreamable>::value &&
|
||||
stream >> output &&
|
||||
stream.get() == std::char_traits<std::stringstream::char_type>::eof();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Input operator
|
||||
@@ -145,7 +134,7 @@ Target stream_cast(const Source& arg)
|
||||
Target result;
|
||||
|
||||
if (!(interpreter << arg && interpreter >> result)) {
|
||||
THROW_CUSTOM_BAD_CAST(bad_stream_cast, typeid(NewSource), typeid(Target));
|
||||
throw bad_stream_cast(typeid(NewSource), typeid(Target));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "type_properties.h" // type_is_*
|
||||
#include "type_categories.h" // type_check_category
|
||||
// #include "static_assert.h" // HZ_STATIC_ASSERT
|
||||
#include "ascii.h" // ascii_*
|
||||
|
||||
|
||||
@@ -208,12 +207,8 @@ DEFINE_STRING_IS_NUMERIC(unsigned int)
|
||||
DEFINE_STRING_IS_NUMERIC(long int)
|
||||
DEFINE_STRING_IS_NUMERIC(unsigned long int)
|
||||
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
DEFINE_STRING_IS_NUMERIC(long long int)
|
||||
#endif
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
DEFINE_STRING_IS_NUMERIC(unsigned long long int)
|
||||
#endif
|
||||
DEFINE_STRING_IS_NUMERIC(long long int)
|
||||
DEFINE_STRING_IS_NUMERIC(unsigned long long int)
|
||||
|
||||
DEFINE_STRING_IS_NUMERIC(float)
|
||||
DEFINE_STRING_IS_NUMERIC(double)
|
||||
@@ -235,13 +230,7 @@ namespace internal {
|
||||
|
||||
|
||||
template<typename T, typename SpecCat = typename type_check_category<T>::type>
|
||||
struct number_to_string_impl {
|
||||
// static std::string func(T number, int alpha_or_base_or_precision, bool ignored_param)
|
||||
// {
|
||||
// HZ_STATIC_ASSERT(hz::static_false<T>::value, not_a_number);
|
||||
// return std::string();
|
||||
// }
|
||||
};
|
||||
struct number_to_string_impl;
|
||||
|
||||
|
||||
// bool spec
|
||||
|
||||
@@ -154,12 +154,8 @@ int main()
|
||||
std::cerr << number_to_string(2L) << "\n"; // long int
|
||||
std::cerr << number_to_string(6) << "\n"; // int
|
||||
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
std::cerr << number_to_string(3LL) << "\n"; // long long int
|
||||
#endif
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
std::cerr << number_to_string(4ULL) << "\n"; // unsigned long long int
|
||||
#endif
|
||||
|
||||
std::cerr << number_to_string(5.f) << "\n"; // float
|
||||
std::cerr << number_to_string(1.33) << "\n"; // double
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <string>
|
||||
|
||||
#include "noncopyable.h"
|
||||
#include "exceptions.h" // THROW_FATAL
|
||||
#include "sync_part_get_policy.h" // internal header, SyncGetPolicy struct.
|
||||
|
||||
|
||||
@@ -294,7 +293,7 @@ struct SyncScopedLockProvider {
|
||||
bool retry()
|
||||
{
|
||||
if (locked_) {
|
||||
THROW_FATAL(sync_resource_error("GenericScopedTryLock::trylock(): Attempting to lock an already locked mutex."));
|
||||
throw sync_resource_error("GenericScopedTryLock::trylock(): Attempting to lock an already locked mutex.");
|
||||
return false;
|
||||
}
|
||||
if (do_lock_)
|
||||
@@ -372,7 +371,7 @@ struct SyncScopedLockProvider {
|
||||
bool retry()
|
||||
{
|
||||
if (locked_) // it's a fatal error, so no point in returning anything.
|
||||
THROW_FATAL(sync_resource_error("GenericScopedRWTryLock::trylock(): Attempting to lock an already locked mutex."));
|
||||
throw sync_resource_error("GenericScopedRWTryLock::trylock(): Attempting to lock an already locked mutex.");
|
||||
if (do_lock_)
|
||||
return (locked_= Policy::trylock(mutex_, for_write_));
|
||||
return true; // it's always success if do_lock was false.
|
||||
@@ -478,7 +477,7 @@ struct SyncPolicyNone {
|
||||
bool retry()
|
||||
{
|
||||
if (do_lock_) // assume that constructor locked it successfully (api-wise).
|
||||
THROW_FATAL(sync_resource_error("GenericScopedTryLock::trylock(): Attempting to lock an already locked mutex."));
|
||||
throw sync_resource_error("GenericScopedTryLock::trylock(): Attempting to lock an already locked mutex.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -524,7 +523,7 @@ struct SyncPolicyNone {
|
||||
bool retry()
|
||||
{
|
||||
if (do_lock_) // assume that constructor locked it successfully (api-wise).
|
||||
THROW_FATAL(sync_resource_error("GenericScopedRWTryLock::trylock(): Attempting to lock an already locked mutex."));
|
||||
throw sync_resource_error("GenericScopedRWTryLock::trylock(): Attempting to lock an already locked mutex.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef HZ_SYNC_POLICY_BOOST_H
|
||||
#define HZ_SYNC_POLICY_BOOST_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "sync.h"
|
||||
|
||||
/**
|
||||
\file
|
||||
Boost.Thread-based policy.
|
||||
*/
|
||||
|
||||
|
||||
// ----------------------------- Boost 1.35 version
|
||||
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
|
||||
|
||||
/// Native type notes:
|
||||
/// Boost scoped_lock doesn't provide the do_lock parameter anymore.
|
||||
/// It has been replaced by boost::defer_lock_type argument.
|
||||
/// There is no single lock for shared_mutex - it has shared_lock and unique_lock.
|
||||
/// We use native types for mutex types here, because they meet the requirements.
|
||||
/// Thus no need to specify locks and other stuff for these separately.
|
||||
struct SyncPolicyBoost : public SyncScopedLockProvider<SyncPolicyBoost> {
|
||||
|
||||
// Types:
|
||||
|
||||
typedef boost::mutex Mutex;
|
||||
typedef Mutex NativeMutex; ///< supports lock(), try_lock(), unlock()
|
||||
|
||||
typedef boost::recursive_mutex RecMutex;
|
||||
typedef RecMutex NativeRecMutex; ///< supports lock(), try_lock(), unlock()
|
||||
|
||||
typedef boost::shared_mutex RWMutex;
|
||||
typedef RWMutex NativeRWMutex; ///< lock(), try_lock(), unlock() - exclusive. *_shared() - shared.
|
||||
|
||||
|
||||
typedef GenericScopedLock<Mutex> ScopedLock;
|
||||
typedef GenericScopedTryLock<Mutex> ScopedTryLock;
|
||||
|
||||
typedef GenericScopedLock<NativeMutex> ScopedNativeLock;
|
||||
typedef GenericScopedTryLock<NativeMutex> ScopedNativeTryLock;
|
||||
|
||||
typedef GenericScopedLock<RecMutex> ScopedRecLock;
|
||||
typedef GenericScopedTryLock<RecMutex> ScopedRecTryLock;
|
||||
|
||||
typedef GenericScopedLock<NativeRecMutex> ScopedNativeRecLock;
|
||||
typedef GenericScopedTryLock<NativeRecMutex> ScopedNativeRecTryLock;
|
||||
|
||||
typedef GenericScopedRWLock<RWMutex> ScopedRWLock;
|
||||
typedef GenericScopedRWTryLock<RWMutex> ScopedRWTryLock;
|
||||
|
||||
typedef GenericScopedRWLock<NativeRWMutex> ScopedNativeRWLock;
|
||||
typedef GenericScopedRWTryLock<NativeRWMutex> ScopedNativeRWTryLock;
|
||||
|
||||
|
||||
// Static methods
|
||||
|
||||
static bool init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void lock(Mutex& m)
|
||||
{
|
||||
try {
|
||||
m.lock();
|
||||
}
|
||||
catch (boost::thread_resource_error& ex) {
|
||||
throw_boost_to_sync_exception(ex, "SyncPolicyBoost::lock(Mutex): Error while locking mutex.");
|
||||
}
|
||||
}
|
||||
|
||||
static bool trylock(Mutex& m)
|
||||
{
|
||||
bool status = false;
|
||||
try {
|
||||
status = m.try_lock();
|
||||
}
|
||||
catch (boost::thread_resource_error& ex) {
|
||||
throw_boost_to_sync_exception(ex, "SyncPolicyBoost::trylock(Mutex): Error while trying to lock mutex.");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void unlock(Mutex& m)
|
||||
{
|
||||
m.unlock(); // this doesn't throw anything
|
||||
}
|
||||
|
||||
|
||||
static void lock(RecMutex& m)
|
||||
{
|
||||
try {
|
||||
m.lock();
|
||||
}
|
||||
catch (boost::thread_resource_error& ex) {
|
||||
throw_boost_to_sync_exception(ex, "SyncPolicyBoost::lock(RecMutex): Error while locking mutex.");
|
||||
}
|
||||
}
|
||||
|
||||
static bool trylock(RecMutex& m)
|
||||
{
|
||||
bool status = false;
|
||||
try {
|
||||
status = m.try_lock();
|
||||
}
|
||||
catch (boost::thread_resource_error& ex) {
|
||||
throw_boost_to_sync_exception(ex, "SyncPolicyBoost::trylock(RecMutex): Error while trying to lock mutex.");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void unlock(RecMutex& m)
|
||||
{
|
||||
m.unlock(); // this doesn't throw anything
|
||||
}
|
||||
|
||||
|
||||
static void lock(RWMutex& m, bool for_write = false)
|
||||
{
|
||||
try {
|
||||
if (for_write) {
|
||||
m.lock();
|
||||
} else {
|
||||
m.lock_shared();
|
||||
}
|
||||
}
|
||||
catch (boost::thread_resource_error& ex) {
|
||||
throw_boost_to_sync_exception(ex, std::string("SyncPolicyBoost::trylock(RWMutex, ")
|
||||
+ (for_write ? "true" : "false") + "): Error while locking mutex.");
|
||||
}
|
||||
}
|
||||
|
||||
static bool trylock(RWMutex& m, bool for_write = false)
|
||||
{
|
||||
bool status = false;
|
||||
try {
|
||||
status = (for_write ? m.try_lock() : m.try_lock_shared());
|
||||
}
|
||||
catch (boost::thread_resource_error& ex) {
|
||||
throw_boost_to_sync_exception(ex, std::string("SyncPolicyBoost::trylock(RWMutex, ")
|
||||
+ (for_write ? "true" : "false") + "): Error while trying to lock mutex.");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void unlock(RWMutex& m, bool for_write = false)
|
||||
{
|
||||
if (for_write) {
|
||||
m.unlock(); // doesn't throw
|
||||
} else {
|
||||
m.unlock_shared(); // doesn't throw
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
static void throw_boost_to_sync_exception(const boost::thread_resource_error& ex, const std::string& smsg)
|
||||
{
|
||||
const char* msg = ex.what();
|
||||
if (msg) {
|
||||
THROW_FATAL(sync_resource_error(smsg
|
||||
+ " Original boost::thread_resource_error exception message: \"" + msg + "\"."));
|
||||
} else {
|
||||
THROW_FATAL(sync_resource_error(smsg
|
||||
+ " This exception was thrown after boost::thread_resource_error was caught (it didn't contain any message)."));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// mutex -> policy
|
||||
|
||||
template<> struct SyncGetPolicy<SyncPolicyBoost::Mutex> { typedef SyncPolicyBoost type; };
|
||||
template<> struct SyncGetPolicy<SyncPolicyBoost::RecMutex> { typedef SyncPolicyBoost type; };
|
||||
template<> struct SyncGetPolicy<SyncPolicyBoost::RWMutex> { typedef SyncPolicyBoost type; };
|
||||
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------- Boost 1.34 version (outdated!)
|
||||
|
||||
/*
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
// #include <boost/thread/read_write_mutex.hpp>
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
|
||||
|
||||
// Provide custom ScopedRWLock class.
|
||||
// class ScopedRWLockBoost : public boost::read_write_mutex::scoped_read_write_lock {
|
||||
// public:
|
||||
// ScopedRWLockBoost(boost::read_write_mutex& mutex, bool for_write = false, bool do_lock = true)
|
||||
// : boost::read_write_mutex::scoped_read_write_lock(mutex, do_lock ?
|
||||
// (for_write ? boost::read_write_lock_state::write_locked : boost::read_write_lock_state::read_locked)
|
||||
// : boost::read_write_lock_state::unlocked)
|
||||
// { }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
// Native type notes:
|
||||
// Boost mutex types support locking through [mutex_type]::scoped_*lock objects only.
|
||||
// We use somewhat undocumented static functions of boost::detail::thread::*lock_ops.
|
||||
|
||||
// Note: Boost Read/Write Mutex is documented, but is unavailable in source form
|
||||
// as of boost 1.34.1. That is, there were some implementation problems in boost, so
|
||||
// it was removed. The policy uses the documented API, but it's disabled until boost
|
||||
// provides a working implementation.
|
||||
|
||||
|
||||
// Classes may use this in single-threaded or non-locking environments
|
||||
struct SyncPolicyBoost {
|
||||
|
||||
typedef boost::try_mutex Mutex; // doesn't have any usable methods
|
||||
typedef boost::try_mutex::scoped_lock ScopedLock; // works well
|
||||
|
||||
typedef boost::recursive_try_mutex RecMutex; // doesn't have any usable methods
|
||||
typedef boost::recursive_try_mutex::scoped_lock ScopedRecLock; // works well
|
||||
|
||||
// typedef boost::try_read_write_mutex RWMutex; // doesn't have any usable methods
|
||||
// typedef ScopedRWLockBoost ScopedRWLock; // needs a wrapper
|
||||
|
||||
static void lock(Mutex& m) { boost::detail::thread::lock_ops<Mutex>::lock(m); }
|
||||
static bool trylock(Mutex& m) { return boost::detail::thread::lock_ops<Mutex>::trylock(m); }
|
||||
static void unlock(Mutex& m) { boost::detail::thread::lock_ops<Mutex>::unlock(m); }
|
||||
|
||||
static void lock(RecMutex& m) { boost::detail::thread::lock_ops<RecMutex>::lock(m); }
|
||||
static bool trylock(RecMutex& m) { return boost::detail::thread::lock_ops<RecMutex>::trylock(m); }
|
||||
static void unlock(RecMutex& m) { boost::detail::thread::lock_ops<RecMutex>::unlock(m); }
|
||||
|
||||
// static void lock(RWMutex& m, bool for_write = false)
|
||||
// {
|
||||
// if (for_write) {
|
||||
// boost::detail::thread::read_write_lock_ops<RWMutex>::write_lock(m);
|
||||
// } else {
|
||||
// boost::detail::thread::read_write_lock_ops<RWMutex>::read_lock(m);
|
||||
// }
|
||||
// }
|
||||
// static bool trylock(RWMutex& m, bool for_write = false)
|
||||
// {
|
||||
// if (for_write)
|
||||
// return boost::detail::thread::read_write_lock_ops<RWMutex>::try_write_lock(m);
|
||||
// }
|
||||
// static void unlock(RWMutex& m, bool for_write = false)
|
||||
// {
|
||||
// if (for_write) {
|
||||
// boost::detail::thread::read_write_lock_ops<RWMutex>::write_unlock(m);
|
||||
// } else {
|
||||
// boost::detail::thread::read_write_lock_ops<RWMutex>::read_unlock(m);
|
||||
// }
|
||||
// }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// mutex -> policy
|
||||
|
||||
template<> struct SyncGetPolicy<SyncPolicyBoost::Mutex> {
|
||||
typedef SyncPolicyBoost type;
|
||||
};
|
||||
|
||||
template<> struct SyncGetPolicy<SyncPolicyBoost::RecMutex> {
|
||||
typedef SyncPolicyBoost type;
|
||||
};
|
||||
|
||||
// template<> struct SyncGetPolicy<SyncPolicyNone::RWMutex> {
|
||||
// typedef SyncPolicyNone type;
|
||||
// };
|
||||
|
||||
|
||||
} // ns
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,113 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef HZ_SYNC_POLICY_POCO_H
|
||||
#define HZ_SYNC_POLICY_POCO_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#include <Poco/Mutex.h>
|
||||
#include <Poco/RWLock.h>
|
||||
|
||||
#include "sync.h"
|
||||
|
||||
|
||||
/**
|
||||
\file
|
||||
Poco-based policy.
|
||||
*/
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
/// Native type notes:
|
||||
/// Poco::Mutex is recursive, while Poco::FastMutex is not.
|
||||
/// Poco::ScopedLock doesn't have "bool do_lock", or anything else for that matter.
|
||||
/// Poco doesn't throw any exceptions for these types, nor does this policy.
|
||||
/// We use native types for mutex types here, because they meet the requirements.
|
||||
/// Thus no need to specify locks and other stuff for these separately.
|
||||
struct SyncPolicyPoco : public SyncScopedLockProvider<SyncPolicyPoco> {
|
||||
|
||||
// Types:
|
||||
|
||||
typedef Poco::FastMutex Mutex;
|
||||
typedef Mutex NativeMutex; ///< supports lock(), tryLock(), unlock()
|
||||
|
||||
typedef Poco::Mutex RecMutex;
|
||||
typedef RecMutex NativeRecMutex; ///< supports lock(), tryLock(), unlock()
|
||||
|
||||
typedef Poco::RWLock RWMutex;
|
||||
typedef RWMutex NativeRWMutex; ///< readLock(), tryReadLock(), writeLock(), tryWriteLock(), unlock().
|
||||
|
||||
|
||||
typedef GenericScopedLock<Mutex> ScopedLock;
|
||||
typedef GenericScopedTryLock<Mutex> ScopedTryLock;
|
||||
|
||||
typedef GenericScopedLock<NativeMutex> ScopedNativeLock;
|
||||
typedef GenericScopedTryLock<NativeMutex> ScopedNativeTryLock;
|
||||
|
||||
typedef GenericScopedLock<RecMutex> ScopedRecLock;
|
||||
typedef GenericScopedTryLock<RecMutex> ScopedRecTryLock;
|
||||
|
||||
typedef GenericScopedLock<NativeRecMutex> ScopedNativeRecLock;
|
||||
typedef GenericScopedTryLock<NativeRecMutex> ScopedNativeRecTryLock;
|
||||
|
||||
typedef GenericScopedRWLock<RWMutex> ScopedRWLock;
|
||||
typedef GenericScopedRWTryLock<RWMutex> ScopedRWTryLock;
|
||||
|
||||
typedef GenericScopedRWLock<NativeRWMutex> ScopedNativeRWLock;
|
||||
typedef GenericScopedRWTryLock<NativeRWMutex> ScopedNativeRWTryLock;
|
||||
|
||||
|
||||
// Static methods
|
||||
|
||||
static bool init() { return true; }
|
||||
|
||||
static void lock(Mutex& m) { m.lock(); }
|
||||
static bool trylock(Mutex& m) { return m.tryLock(); }
|
||||
static void unlock(Mutex& m) { m.unlock(); }
|
||||
|
||||
static void lock(RecMutex& m) { m.lock(); }
|
||||
static bool trylock(RecMutex& m) { return m.tryLock(); }
|
||||
static void unlock(RecMutex& m) { m.unlock(); }
|
||||
|
||||
static void lock(RWMutex& m, bool for_write = false)
|
||||
{
|
||||
if (for_write) {
|
||||
m.writeLock();
|
||||
} else {
|
||||
m.readLock();
|
||||
}
|
||||
}
|
||||
static bool trylock(RWMutex& m, bool for_write = false)
|
||||
{
|
||||
return (for_write ? m.tryWriteLock() : m.tryReadLock());
|
||||
}
|
||||
static void unlock(RWMutex& m, bool for_write = false)
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// mutex -> policy
|
||||
|
||||
template<> struct SyncGetPolicy<SyncPolicyPoco::Mutex> { typedef SyncPolicyPoco type; };
|
||||
template<> struct SyncGetPolicy<SyncPolicyPoco::RecMutex> { typedef SyncPolicyPoco type; };
|
||||
template<> struct SyncGetPolicy<SyncPolicyPoco::RWMutex> { typedef SyncPolicyPoco type; };
|
||||
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -54,9 +54,9 @@ namespace internal {
|
||||
inline void sync_pthread_throw_exception(const std::string& msg, int errno_value = 0)
|
||||
{
|
||||
if (errno_value == 0) {
|
||||
THROW_FATAL(sync_resource_error(msg));
|
||||
throw (sync_resource_error(msg));
|
||||
} else {
|
||||
THROW_FATAL(sync_resource_error(msg + " Errno: " + hz::errno_string(errno_value)));
|
||||
throw (sync_resource_error(msg + " Errno: " + hz::errno_string(errno_value)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class MutexWin32 : public hz::noncopyable {
|
||||
EnterCriticalSection(&mutex);
|
||||
}
|
||||
catch (...) {
|
||||
THROW_FATAL(sync_resource_error("MutexWin32::native_lock(): Error locking mutex."));
|
||||
throw (sync_resource_error("MutexWin32::native_lock(): Error locking mutex."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class MutexWin32 : public hz::noncopyable {
|
||||
res = TryEnterCriticalSection(&mutex);
|
||||
}
|
||||
catch (...) {
|
||||
THROW_FATAL(sync_resource_error("MutexWin32::native_trylock(): Error trying to lock mutex."));
|
||||
throw (sync_resource_error("MutexWin32::native_trylock(): Error trying to lock mutex."));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -70,7 +70,7 @@ class MutexWin32 : public hz::noncopyable {
|
||||
LeaveCriticalSection(&mutex);
|
||||
}
|
||||
catch (...) {
|
||||
THROW_FATAL(sync_resource_error("MutexWin32::native_unlock(): Error unlocking mutex."));
|
||||
throw (sync_resource_error("MutexWin32::native_unlock(): Error unlocking mutex."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +80,10 @@ class MutexWin32 : public hz::noncopyable {
|
||||
try {
|
||||
// MSDN says 4000 is a good value. has effect only for SMP.
|
||||
if (!InitializeCriticalSectionAndSpinCount(&cs_, 4000))
|
||||
THROW_FATAL(sync_resource_error("MutexWin32::MutexWin32(): Error creating mutex."));
|
||||
throw (sync_resource_error("MutexWin32::MutexWin32(): Error creating mutex."));
|
||||
}
|
||||
catch (...) {
|
||||
THROW_FATAL(sync_resource_error("MutexWin32::MutexWin32(): Error creating mutex."));
|
||||
throw (sync_resource_error("MutexWin32::MutexWin32(): Error creating mutex."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ class MutexWin32 : public hz::noncopyable {
|
||||
DeleteCriticalSection(&cs_);
|
||||
}
|
||||
catch (...) {
|
||||
THROW_FATAL(sync_resource_error("MutexWin32::MutexWin32(): Error destroying mutex."));
|
||||
throw (sync_resource_error("MutexWin32::MutexWin32(): Error destroying mutex."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
}
|
||||
}
|
||||
}
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::RWMutexWin32(): Error creating read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::RWMutexWin32(): Error creating read/write lock."));
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
CloseHandle(write_event_);
|
||||
}
|
||||
catch (...) {
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::~RWMutexWin32(): Error destroying read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::~RWMutexWin32(): Error destroying read/write lock."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
|
||||
} else {
|
||||
remove_writer();
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::lock(): Error write-locking a read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::lock(): Error write-locking a read/write lock."));
|
||||
}
|
||||
|
||||
} else { // read:
|
||||
@@ -171,7 +171,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
ReleaseMutex(mutex_);
|
||||
|
||||
} else {
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::lock(): Error read-locking a read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::lock(): Error read-locking a read/write lock."));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
} else {
|
||||
remove_writer();
|
||||
if (res != WAIT_TIMEOUT)
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::trylock(): Error while trying to write-lock a read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::trylock(): Error while trying to write-lock a read/write lock."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
|
||||
} else {
|
||||
if (res != WAIT_TIMEOUT)
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::trylock(): Error while trying to read-lock a read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::trylock(): Error while trying to read-lock a read/write lock."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -227,7 +227,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
ReleaseMutex(mutex_);
|
||||
return;
|
||||
}
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::unlock(): Error while unlocking a read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::unlock(): Error while unlocking a read/write lock."));
|
||||
}
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
ReleaseMutex(mutex_);
|
||||
return;
|
||||
}
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::add_writer(): Error while locking a read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::add_writer(): Error while locking a read/write lock."));
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ class RWMutexWin32 : public hz::noncopyable {
|
||||
ReleaseMutex(mutex_);
|
||||
return;
|
||||
}
|
||||
THROW_FATAL(sync_resource_error("RWMutexWin32::remove_writer(): Error while locking a read/write lock."));
|
||||
throw (sync_resource_error("RWMutexWin32::remove_writer(): Error while locking a read/write lock."));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,440 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz
|
||||
/// \weakgroup hz
|
||||
/// @{
|
||||
|
||||
#ifndef HZ_TLS_H
|
||||
#define HZ_TLS_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#include <cstdlib> // std::free()
|
||||
|
||||
// Don't use DBG_ASSERT() here, it's using this library and therefore
|
||||
// too error-prone to use in this context.
|
||||
#include <cassert>
|
||||
#ifndef ASSERT // assert() is undefined if NDEBUG is defined.
|
||||
#define ASSERT(a) assert(a)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\file
|
||||
Thread-local storage.
|
||||
|
||||
Notes on various policies:
|
||||
|
||||
Poco-based policy cannot be implemented because Poco's ThreadLocal
|
||||
lacks some vital methods, e.g. setting it to an existing pointer (it creates
|
||||
the object itself), or specifying a destroy function (it just deletes the pointer).
|
||||
|
||||
Glibmm-based policy has been implemented but it had problems
|
||||
with calling the destructor function (not calling it at all), plus it's completely
|
||||
redundant with availability of Glib policy.
|
||||
|
||||
Win32-based policy doesn't have on-thread-exit cleanup function support
|
||||
due to technical limitations of MS design. Cleanup functions are called
|
||||
on object destruction and reset(), however. If this is a major problem,
|
||||
use Glib, pthread-win32 or Boost policies instead (they have some
|
||||
dll-specific workarounds implemented).
|
||||
See win32 policy file for details.
|
||||
*/
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
/// TLS policy suitable for single-threaded model.
|
||||
struct TlsPolicyNone {
|
||||
typedef void (*native_cleanup_func_t)(void*);
|
||||
|
||||
TlsPolicyNone(native_cleanup_func_t native_cleanup)
|
||||
: native_cleanup_(native_cleanup), inited_(false), p_(0)
|
||||
{ }
|
||||
|
||||
~TlsPolicyNone()
|
||||
{
|
||||
if (inited_ && native_cleanup_)
|
||||
native_cleanup_(get());
|
||||
}
|
||||
|
||||
void* get() const
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
void reset(void* p)
|
||||
{
|
||||
// call the cleanup function for the previous pointer.
|
||||
if (inited_ && native_cleanup_)
|
||||
native_cleanup_(p_);
|
||||
if (p)
|
||||
inited_ = true;
|
||||
p_ = p;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
native_cleanup_func_t native_cleanup_; ///< may be NULL
|
||||
bool inited_;
|
||||
void* p_;
|
||||
|
||||
TlsPolicyNone(const TlsPolicyNone&);
|
||||
TlsPolicyNone& operator= (const TlsPolicyNone& from);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \class TlsPolicyMtDefault
|
||||
/// Default TLS policy for thread_local_ptr.
|
||||
|
||||
#if defined HZ_TLS_DEFAULT_POLICY_GLIB
|
||||
#include "tls_policy_glib.h"
|
||||
namespace hz {
|
||||
typedef TlsPolicyGlib TlsPolicyMtDefault;
|
||||
}
|
||||
|
||||
#elif defined HZ_TLS_DEFAULT_POLICY_BOOST
|
||||
// No header here. The header contains thread_local_ptr specialization,
|
||||
// therefore it must be after thread_local_ptr (see below).
|
||||
namespace hz {
|
||||
// Note: TlsPolicyMtDefault should be before thread_local_ptr - it's
|
||||
// used as its default template argument.
|
||||
struct TlsPolicyBoost { }; // dummy, only to help specialization
|
||||
|
||||
typedef TlsPolicyBoost TlsPolicyMtDefault;
|
||||
}
|
||||
|
||||
#elif defined HZ_TLS_DEFAULT_POLICY_PTHREAD
|
||||
#include "tls_policy_pthread.h"
|
||||
namespace hz {
|
||||
typedef TlsPolicyPthread TlsPolicyMtDefault;
|
||||
}
|
||||
|
||||
|
||||
#elif defined HZ_TLS_DEFAULT_POLICY_WIN32
|
||||
#include "tls_policy_win32.h"
|
||||
namespace hz {
|
||||
typedef TlsPolicyWin32 TlsPolicyMtDefault;
|
||||
}
|
||||
|
||||
#else // default: NONE
|
||||
// #elif defined HZ_TLS_DEFAULT_POLICY_NONE // default:
|
||||
namespace hz {
|
||||
typedef TlsPolicyNone TlsPolicyMtDefault;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
|
||||
namespace internal {
|
||||
|
||||
/// Base class, needed to distinguish between actual and void* specialization
|
||||
template<typename T, class TlsPolicy>
|
||||
class thread_local_ptr_base {
|
||||
|
||||
protected:
|
||||
|
||||
/// Constructor, takes policy object
|
||||
template<typename PolicyArg>
|
||||
thread_local_ptr_base(PolicyArg cleanup) : policy_(cleanup)
|
||||
{ }
|
||||
|
||||
public:
|
||||
|
||||
/// Destructor, deletes the pointer.
|
||||
~thread_local_ptr_base()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
/// Get the wrapped pointer
|
||||
T* get() const
|
||||
{
|
||||
return static_cast<T*>(policy_.get());
|
||||
}
|
||||
|
||||
/// Get the wrapped pointer and call reset().
|
||||
/// FIXME Is this correct (returning T* after reset())?
|
||||
T* release()
|
||||
{
|
||||
T* tmp = get();
|
||||
reset();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/// Reset the pointer (delete it), taking ownership of the new one.
|
||||
void reset(T* p = 0)
|
||||
{
|
||||
if (get() == p)
|
||||
return;
|
||||
// this will call the cleanup function for the previous pointer
|
||||
policy_.reset(static_cast<void*>(p));
|
||||
}
|
||||
|
||||
/// Check policy capabilities - whether cleanup is supported
|
||||
bool cleanup_supported()
|
||||
{
|
||||
return TlsPolicy::cleanup_supported;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
TlsPolicy policy_; ///< The policy object
|
||||
};
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------- C++-style cleanup function linkage
|
||||
|
||||
|
||||
/**
|
||||
Note: These functions have C++ linkage. It is impossible to make
|
||||
them extern "C", because they are templates. Moving to void* arguments
|
||||
is also invalid, because C++ operator delete cannot reliably delete a
|
||||
void* pointer (destructor may not get called, etc...).
|
||||
|
||||
C linkage _may_ be needed if:
|
||||
1. The compiler doesn't support calling C++ functions by pointers from
|
||||
C code, AND
|
||||
2. The underlying TLS implementation is in C (e.g. GLib, pthread, etc...).
|
||||
Note that this may not affect implementations which do implement their
|
||||
own callback system (e.g. Boost).
|
||||
|
||||
If you desperately need C linkage, you may define your own C-linked callback.
|
||||
However, note that you MUST NOT delete the resulting pointer with delete
|
||||
operator if it's void*.
|
||||
Note: There may be problems when passing extern "C" function as a template
|
||||
parameter to non-extern "C" class template (sun compiler).
|
||||
*/
|
||||
template<typename T>
|
||||
struct tls_functions {
|
||||
/// This will be called by default if no cleanup function has been set.
|
||||
static void cleanup_delete(T* p) { delete p; }
|
||||
|
||||
/// Use this for delete[]
|
||||
static void cleanup_delete_array(T* p) { delete[] p; }
|
||||
|
||||
/// Use this for C's free()
|
||||
static void cleanup_free(T* p) { std::free(p); }
|
||||
|
||||
/// Use this for no cleanup
|
||||
static void nothing(T* p) { } // Note: This will work with C linkage too, because it's not actually called.
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Thread-local pointer.
|
||||
template<typename T, class TlsPolicy = TlsPolicyMtDefault,
|
||||
void cleanup_func(T*) = tls_functions<T>::cleanup_delete>
|
||||
class thread_local_ptr : public internal::thread_local_ptr_base<T, TlsPolicy> {
|
||||
|
||||
// This class cannot support DefaultType, because it may be specialized by TlsPolicy parameter.
|
||||
// typedef typename type_auto_select<TlsPolicy_, TlsPolicyMtDefault>::type TlsPolicy; // support DefaultType
|
||||
|
||||
typedef internal::thread_local_ptr_base<T, TlsPolicy> base; ///< Base class
|
||||
typedef thread_local_ptr<T, TlsPolicy, cleanup_func> self_type; ///< Self type
|
||||
|
||||
public:
|
||||
using base::get;
|
||||
using base::release;
|
||||
using base::reset;
|
||||
using base::cleanup_supported;
|
||||
|
||||
/// Constructor
|
||||
thread_local_ptr()
|
||||
: base(cleanup_func == tls_functions<T>::nothing ? NULL : &cleanup_proxy)
|
||||
{ }
|
||||
|
||||
/// Arrow operator
|
||||
T* operator->() const { return get(); }
|
||||
|
||||
/// Dereference operator
|
||||
T& operator*() const
|
||||
{
|
||||
T* cur = get();
|
||||
ASSERT(cur);
|
||||
return *cur;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/// Disallow copying
|
||||
thread_local_ptr(const self_type&);
|
||||
|
||||
/// Disallow copying
|
||||
thread_local_ptr& operator= (const self_type& from);
|
||||
|
||||
/// Internal proxy function. This is called by the underlying implementation.
|
||||
/// Note: This should have been a C linkage function, because its pointer may
|
||||
/// be passed to C functions. However, we can't do that because it's a template.
|
||||
/// So we rely on compiler to support passing C++ function pointers to C functions.
|
||||
static void cleanup_proxy(void* p)
|
||||
{
|
||||
cleanup_func(static_cast<T*>(p));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// void* specialization of thread_local_ptr. Disallows operator*.
|
||||
template<class TlsPolicy, void cleanup_func(void*)>
|
||||
class thread_local_ptr<void, TlsPolicy, cleanup_func>
|
||||
: public internal::thread_local_ptr_base<void, TlsPolicy> {
|
||||
|
||||
typedef internal::thread_local_ptr_base<void, TlsPolicy> base;
|
||||
typedef thread_local_ptr<void, TlsPolicy, cleanup_func> self_type;
|
||||
|
||||
public:
|
||||
using base::get;
|
||||
using base::release;
|
||||
using base::reset;
|
||||
using base::cleanup_supported;
|
||||
|
||||
thread_local_ptr() : base(cleanup_func == tls_functions<void>::nothing ? NULL : cleanup_func)
|
||||
{ }
|
||||
|
||||
void* operator->() const { return get(); }
|
||||
|
||||
private:
|
||||
thread_local_ptr(const self_type&);
|
||||
thread_local_ptr& operator= (const self_type& from);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------- C-style cleanup function linkage
|
||||
|
||||
|
||||
|
||||
/// C functions for T=void.
|
||||
extern "C" {
|
||||
|
||||
/// Cleanup function type for void*, with C linkage.
|
||||
typedef void (tls_cleanup_c_func_t)(void*);
|
||||
|
||||
/// A function that calls std::free(). C-linkage.
|
||||
inline void tls_cleanup_c_free(void* p)
|
||||
{
|
||||
std::free(p);
|
||||
}
|
||||
|
||||
/// A function that does nothing. C-linkage.
|
||||
inline void tls_cleanup_c_nothing(void* p)
|
||||
{ }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Same as thread_local_ptr, but uses C-linkage functions for cleanup.
|
||||
template<typename T, class TlsPolicy = TlsPolicyMtDefault,
|
||||
tls_cleanup_c_func_t cleanup_func = tls_cleanup_c_free>
|
||||
class thread_local_c_ptr : public internal::thread_local_ptr_base<T, TlsPolicy> {
|
||||
|
||||
typedef internal::thread_local_ptr_base<T, TlsPolicy> base; ///< Base class
|
||||
typedef thread_local_ptr<T, TlsPolicy, cleanup_func> self_type; ///< Self type
|
||||
|
||||
public:
|
||||
using base::get;
|
||||
using base::release;
|
||||
using base::reset;
|
||||
using base::cleanup_supported;
|
||||
|
||||
/// Constructor
|
||||
thread_local_c_ptr() : base(cleanup_func == tls_cleanup_c_nothing ? NULL : cleanup_func)
|
||||
{ }
|
||||
|
||||
/// Arrow operator
|
||||
T* operator->() const { return get(); }
|
||||
|
||||
/// Dereference operator
|
||||
T& operator*() const
|
||||
{
|
||||
T* cur = get();
|
||||
ASSERT(cur);
|
||||
return *cur;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/// Disallow copying
|
||||
thread_local_c_ptr(const self_type&);
|
||||
|
||||
/// Disallow copying
|
||||
thread_local_c_ptr& operator= (const self_type& from);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// void* specialization for thread_local_c_ptr. Disallows operator*.
|
||||
template<class TlsPolicy, tls_cleanup_c_func_t cleanup_func>
|
||||
class thread_local_c_ptr<void, TlsPolicy, cleanup_func>
|
||||
: public internal::thread_local_ptr_base<void, TlsPolicy> {
|
||||
|
||||
typedef internal::thread_local_ptr_base<void, TlsPolicy> base;
|
||||
typedef thread_local_ptr<void, TlsPolicy, cleanup_func> self_type;
|
||||
|
||||
public:
|
||||
using base::get;
|
||||
using base::release;
|
||||
using base::reset;
|
||||
using base::cleanup_supported;
|
||||
|
||||
thread_local_c_ptr() : base(cleanup_func == tls_cleanup_c_nothing ? NULL : cleanup_func)
|
||||
{ }
|
||||
|
||||
void* operator->() const { return get(); }
|
||||
|
||||
private:
|
||||
thread_local_c_ptr(const self_type&);
|
||||
thread_local_c_ptr& operator= (const self_type& from);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
// must be after thread_local_ptr
|
||||
#if defined HZ_TLS_DEFAULT_POLICY_BOOST
|
||||
#include "tls_policy_boost.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -1,104 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz
|
||||
/// \weakgroup hz
|
||||
/// @{
|
||||
|
||||
#ifndef HZ_TLS_BOOST_H
|
||||
#define HZ_TLS_BOOST_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
|
||||
/**
|
||||
\file
|
||||
Boost-based thread-local storage.
|
||||
*/
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
// TlsPolicyBoost is declared in tls.h.
|
||||
|
||||
|
||||
// Our class mimics boost::thread_specific_ptr<> in its API,
|
||||
// so we may just wrap it without any changes.
|
||||
|
||||
template<typename T, void cleanup_func(T*)>
|
||||
class thread_local_ptr<T, TlsPolicyBoost, cleanup_func>
|
||||
: public boost::thread_specific_ptr<T> {
|
||||
|
||||
public:
|
||||
thread_local_ptr() : boost::thread_specific_ptr<T>(cleanup_func)
|
||||
{ }
|
||||
|
||||
static const bool cleanup_supported = true;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// boost doesn't support void*, but we still need to specialize to avoid
|
||||
// ambigous situations.
|
||||
template<void cleanup_func(void*)>
|
||||
class thread_local_ptr<void, TlsPolicyBoost, cleanup_func> {
|
||||
|
||||
public:
|
||||
thread_local_ptr() { }
|
||||
|
||||
// these should trigger the errors
|
||||
void get() { }
|
||||
void reset() { }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// These two will work if the compiler supports passing C functions
|
||||
// to C++-linkage template arguments
|
||||
|
||||
template<typename T, tls_cleanup_c_func_t cleanup_func>
|
||||
class thread_local_c_ptr<T, TlsPolicyBoost, cleanup_func>
|
||||
: public boost::thread_specific_ptr<T> {
|
||||
|
||||
public:
|
||||
thread_local_c_ptr() : boost::thread_specific_ptr<T>(cleanup_func)
|
||||
{ }
|
||||
|
||||
static const bool cleanup_supported = true;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// boost doesn't support void*, but we still need to specialize to avoid
|
||||
// ambigous situations.
|
||||
template<tls_cleanup_c_func_t cleanup_func>
|
||||
class thread_local_c_ptr<void, TlsPolicyBoost, cleanup_func> {
|
||||
|
||||
public:
|
||||
thread_local_c_ptr() { }
|
||||
|
||||
// these should trigger the errors
|
||||
void get() { }
|
||||
void reset() { }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -1,151 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz
|
||||
/// \weakgroup hz
|
||||
/// @{
|
||||
|
||||
#ifndef HZ_TLS_POLICY_GLIB_H
|
||||
#define HZ_TLS_POLICY_GLIB_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
||||
/**
|
||||
\file
|
||||
Glib-based thread-local storage.
|
||||
*/
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
extern "C" {
|
||||
typedef void (*tls_policy_glib_cleanup_func_t)(void*);
|
||||
}
|
||||
|
||||
// suncc needs this
|
||||
#if defined HAVE_CXX_EXTERN_C_OVERLOAD && HAVE_CXX_EXTERN_C_OVERLOAD
|
||||
typedef void (*tls_policy_glib_cleanup_func_cpp_t)(void*);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if GLIB_CHECK_VERSION(2, 32, 0)
|
||||
|
||||
|
||||
/// Glib-based TLS policy
|
||||
class TlsPolicyGlib {
|
||||
public:
|
||||
|
||||
TlsPolicyGlib(tls_policy_glib_cleanup_func_t native_cleanup)
|
||||
: key_((GPrivate)G_PRIVATE_INIT(native_cleanup))
|
||||
{ }
|
||||
|
||||
#if defined HAVE_CXX_EXTERN_C_OVERLOAD && HAVE_CXX_EXTERN_C_OVERLOAD
|
||||
TlsPolicyGlib(tls_policy_glib_cleanup_func_cpp_t native_cleanup)
|
||||
: key_((GPrivate)G_PRIVATE_INIT(native_cleanup))
|
||||
{ }
|
||||
#endif
|
||||
|
||||
~TlsPolicyGlib()
|
||||
{
|
||||
// Nothing
|
||||
}
|
||||
|
||||
void* get() const
|
||||
{
|
||||
return g_private_get(&key_);
|
||||
}
|
||||
|
||||
void reset(void* p)
|
||||
{
|
||||
// this will call the cleanup function for the previous pointer
|
||||
g_private_replace(&key_, static_cast<gpointer>(p));
|
||||
}
|
||||
|
||||
|
||||
static const bool cleanup_supported = true;
|
||||
|
||||
private:
|
||||
|
||||
mutable GPrivate key_;
|
||||
|
||||
TlsPolicyGlib(const TlsPolicyGlib&);
|
||||
TlsPolicyGlib& operator= (const TlsPolicyGlib& from);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#else // old glib
|
||||
|
||||
|
||||
|
||||
/// Glib-based TLS policy
|
||||
class TlsPolicyGlib {
|
||||
public:
|
||||
|
||||
TlsPolicyGlib(tls_policy_glib_cleanup_func_t native_cleanup) : native_cleanup_(native_cleanup)
|
||||
{
|
||||
g_static_private_init(&key_);
|
||||
}
|
||||
|
||||
#if defined HAVE_CXX_EXTERN_C_OVERLOAD && HAVE_CXX_EXTERN_C_OVERLOAD
|
||||
TlsPolicyGlib(tls_policy_glib_cleanup_func_cpp_t native_cleanup) : native_cleanup_(native_cleanup)
|
||||
{
|
||||
g_static_private_init(&key_);
|
||||
}
|
||||
#endif
|
||||
|
||||
~TlsPolicyGlib()
|
||||
{
|
||||
// if this object is not static, then it will die before the thread.
|
||||
// g_static_private_free() will call the destructor function if the key was associated
|
||||
// with a non-NULL value at least once.
|
||||
g_static_private_free(&key_);
|
||||
}
|
||||
|
||||
void* get() const
|
||||
{
|
||||
return g_static_private_get(&key_);
|
||||
}
|
||||
|
||||
void reset(void* p)
|
||||
{
|
||||
// this will call the cleanup function for the previous pointer
|
||||
g_static_private_set(&key_, static_cast<gpointer>(p), native_cleanup_);
|
||||
}
|
||||
|
||||
|
||||
static const bool cleanup_supported = true;
|
||||
|
||||
private:
|
||||
|
||||
mutable GStaticPrivate key_;
|
||||
tls_policy_glib_cleanup_func_t native_cleanup_; ///< may be NULL
|
||||
|
||||
TlsPolicyGlib(const TlsPolicyGlib&);
|
||||
TlsPolicyGlib& operator= (const TlsPolicyGlib& from);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -1,122 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz
|
||||
/// \weakgroup hz
|
||||
/// @{
|
||||
|
||||
#ifndef HZ_TLS_POLICY_PTHREAD_H
|
||||
#define HZ_TLS_POLICY_PTHREAD_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
// Don't use DBG_ASSERT() here, it's using this library and therefore
|
||||
// too error-prone to use in this context.
|
||||
#include <cassert>
|
||||
#ifndef ASSERT // assert() is undefined if NDEBUG is defined.
|
||||
#define ASSERT(a) assert(a)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\file
|
||||
Pthreads-based thread-local storage.
|
||||
Note that cleanup-function calling policy emulates the Glib one.
|
||||
*/
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
extern "C" {
|
||||
typedef void (*tls_policy_pthread_cleanup_func_t)(void*);
|
||||
}
|
||||
|
||||
// suncc needs this
|
||||
#if defined HAVE_CXX_EXTERN_C_OVERLOAD && HAVE_CXX_EXTERN_C_OVERLOAD
|
||||
typedef void (*tls_policy_pthread_cleanup_cpp_func_t)(void*);
|
||||
#endif
|
||||
|
||||
|
||||
/// Pthreads-based TLS policy
|
||||
class TlsPolicyPthread {
|
||||
public:
|
||||
|
||||
TlsPolicyPthread(tls_policy_pthread_cleanup_func_t native_cleanup)
|
||||
: native_cleanup_(native_cleanup), inited_(false)
|
||||
{
|
||||
int res = pthread_key_create(&key_, native_cleanup);
|
||||
ASSERT(res == 0);
|
||||
}
|
||||
|
||||
#if defined HAVE_CXX_EXTERN_C_OVERLOAD && HAVE_CXX_EXTERN_C_OVERLOAD
|
||||
TlsPolicyPthread(tls_policy_pthread_cleanup_cpp_func_t native_cleanup) : native_cleanup_(native_cleanup)
|
||||
{
|
||||
int res = pthread_key_create(&key_, native_cleanup);
|
||||
ASSERT(res == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
~TlsPolicyPthread()
|
||||
{
|
||||
// if this object is not static, then it will die before the thread.
|
||||
// pthread_key_delete() won't call the destructor function, so call it manually.
|
||||
if (inited_ && native_cleanup_)
|
||||
native_cleanup_(get());
|
||||
|
||||
int res = pthread_key_delete(key_);
|
||||
ASSERT(res == 0);
|
||||
}
|
||||
|
||||
void* get() const
|
||||
{
|
||||
return pthread_getspecific(key_);
|
||||
}
|
||||
|
||||
void reset(void* p)
|
||||
{
|
||||
// call the cleanup function for the previous pointer.
|
||||
if (inited_ && native_cleanup_)
|
||||
native_cleanup_(get());
|
||||
|
||||
if (p)
|
||||
inited_ = true;
|
||||
|
||||
int res = pthread_setspecific(key_, p);
|
||||
ASSERT(res == 0);
|
||||
}
|
||||
|
||||
|
||||
static const bool cleanup_supported = true;
|
||||
|
||||
private:
|
||||
|
||||
pthread_key_t key_;
|
||||
tls_policy_pthread_cleanup_func_t native_cleanup_; // may be NULL
|
||||
bool inited_; // if the key has been associated with the non-NULL value at least once.
|
||||
|
||||
TlsPolicyPthread(const TlsPolicyPthread&);
|
||||
TlsPolicyPthread& operator= (const TlsPolicyPthread& from);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -1,115 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_zlib.txt file
|
||||
***************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup hz
|
||||
/// \weakgroup hz
|
||||
/// @{
|
||||
|
||||
#ifndef HZ_TLS_POLICY_WIN32_H
|
||||
#define HZ_TLS_POLICY_WIN32_H
|
||||
|
||||
#include "hz_config.h" // feature macros
|
||||
|
||||
#ifndef _WIN32
|
||||
#error Cannot compile a win32-only file under non-win32 system
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Don't use DBG_ASSERT() here, it's using this library and therefore
|
||||
// too error-prone to use in this context.
|
||||
#include <cassert>
|
||||
#ifndef ASSERT // assert() is undefined if NDEBUG is defined.
|
||||
#define ASSERT(a) assert(a)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\file
|
||||
Win32-threads-based thread-local storage.
|
||||
|
||||
NOTE On-thread-exit cleanup functions ARE NOT implemented.
|
||||
They are called on object destruction and reset(), however.
|
||||
Implementing on-thread-exit callbacks requires some really ugly
|
||||
hacks, introducing some really ugly problems and limitations.
|
||||
See http://lists.boost.org/Archives/boost/2003/02/44905.php
|
||||
*/
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
/// Win32-threads-based TLS policy
|
||||
class TlsPolicyWin32 {
|
||||
public:
|
||||
|
||||
typedef void (*native_cleanup_func_t)(void*);
|
||||
|
||||
TlsPolicyWin32(native_cleanup_func_t native_cleanup)
|
||||
: native_cleanup_(native_cleanup), inited_(false)
|
||||
{
|
||||
key_ = TlsAlloc(); // sets data to 0.
|
||||
ASSERT(key_ != TLS_OUT_OF_INDEXES);
|
||||
}
|
||||
|
||||
~TlsPolicyWin32()
|
||||
{
|
||||
// call cleanup manually
|
||||
if (inited_ && native_cleanup_)
|
||||
native_cleanup_(get());
|
||||
|
||||
if (key_ != TLS_OUT_OF_INDEXES) {
|
||||
BOOL res = TlsFree(key_);
|
||||
ASSERT(res != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void* get() const
|
||||
{
|
||||
void* p = TlsGetValue(key_);
|
||||
ASSERT(p || GetLastError() == ERROR_SUCCESS); // if p is 0, check last error
|
||||
return p;
|
||||
}
|
||||
|
||||
void reset(void* p)
|
||||
{
|
||||
// call the cleanup function for the previous pointer.
|
||||
if (inited_ && native_cleanup_)
|
||||
native_cleanup_(get());
|
||||
|
||||
if (p)
|
||||
inited_ = true;
|
||||
|
||||
BOOL res = TlsSetValue(key_, p);
|
||||
ASSERT(res != 0);
|
||||
}
|
||||
|
||||
|
||||
static const bool cleanup_supported = false;
|
||||
|
||||
private:
|
||||
|
||||
DWORD key_;
|
||||
native_cleanup_func_t native_cleanup_; ///< may be NULL
|
||||
bool inited_; ///< True if the key has been associated with the non-NULL value at least once.
|
||||
|
||||
TlsPolicyWin32(const TlsPolicyWin32&);
|
||||
TlsPolicyWin32& operator= (const TlsPolicyWin32& from);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // ns
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -1,106 +0,0 @@
|
||||
/**************************************************************************
|
||||
Copyright:
|
||||
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
|
||||
License: See LICENSE_unlicense.txt
|
||||
***************************************************************************/
|
||||
|
||||
// disable libdebug, we don't link to it
|
||||
#undef HZ_USE_LIBDEBUG
|
||||
#define HZ_USE_LIBDEBUG 0
|
||||
// enable libdebug emulation through std::cerr
|
||||
#undef HZ_EMULATE_LIBDEBUG
|
||||
#define HZ_EMULATE_LIBDEBUG 1
|
||||
|
||||
|
||||
// If none are defined and there are no undefs below, the default
|
||||
// policy is used (see global_macros.h).
|
||||
|
||||
/*
|
||||
#undef HZ_TLS_DEFAULT_POLICY_GLIB
|
||||
#undef HZ_TLS_DEFAULT_POLICY_BOOST
|
||||
#undef HZ_TLS_DEFAULT_POLICY_PTHREAD
|
||||
#undef HZ_TLS_DEFAULT_POLICY_WIN32
|
||||
|
||||
// #define HZ_TLS_DEFAULT_POLICY_GLIB
|
||||
// #define HZ_TLS_DEFAULT_POLICY_BOOST
|
||||
#define HZ_TLS_DEFAULT_POLICY_PTHREAD
|
||||
// #define HZ_TLS_DEFAULT_POLICY_WIN32
|
||||
*/
|
||||
|
||||
// The first header should be then one we're testing, to avoid missing
|
||||
// header pitfalls.
|
||||
#include "tls.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
|
||||
// For those compilers who don't support mixing C- and C++-style
|
||||
// linkage functions in function pointers, you should use a special
|
||||
// thread_local_c_ptr<> variant.
|
||||
|
||||
// C++-style, for thread_local_ptr<>
|
||||
inline void custom_cleanup(int* p)
|
||||
{
|
||||
std::cerr << "Calling custom_cleanup with p=" << p << "\n";
|
||||
delete p;
|
||||
}
|
||||
|
||||
// C-style, for thread_local_c_ptr<>
|
||||
inline void custom_cleanup_c(void* p)
|
||||
{
|
||||
std::cerr << "Calling custom_cleanup_c with p=" << p << "\n";
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace hz;
|
||||
|
||||
// g_thread_init(NULL);
|
||||
|
||||
|
||||
{
|
||||
thread_local_ptr<int, TlsPolicyMtDefault> p;
|
||||
|
||||
p.reset(new int(5));
|
||||
std::cerr << *p << "\n";
|
||||
|
||||
p.reset(new int(6));
|
||||
std::cerr << *p << "\n";
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
thread_local_ptr<int, TlsPolicyMtDefault, custom_cleanup> p;
|
||||
// static thread_local_ptr<int, TlsPolicyMtDefault, custom_cleanup> p;
|
||||
|
||||
// void* pointers
|
||||
// thread_local_ptr<void, TlsPolicyMtDefault, tls_cleanup_c_free> p; // g++ yes, intel yes, sun no.
|
||||
// thread_local_c_ptr<void, TlsPolicyMtDefault, tls_cleanup_c_free> p; // all yes.
|
||||
|
||||
p.reset(new int(7));
|
||||
// should be NO cleanup here
|
||||
// std::cerr << *p << "\n";
|
||||
|
||||
p.reset();
|
||||
// should call cleanup here
|
||||
std::cerr << p.get() << "\n";
|
||||
// should call cleanup here if NOT static
|
||||
}
|
||||
|
||||
std::cerr << "All OK\n";
|
||||
|
||||
// should call cleanup here if _static_
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -47,12 +47,8 @@ template<> struct type_check_arithmetic<int> { typedef type_arithm_integral type
|
||||
template<> struct type_check_arithmetic<unsigned int> { typedef type_arithm_integral type; };
|
||||
template<> struct type_check_arithmetic<long int> { typedef type_arithm_integral type; };
|
||||
template<> struct type_check_arithmetic<unsigned long int> { typedef type_arithm_integral type; };
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
template<> struct type_check_arithmetic<long long int> { typedef type_arithm_integral type; };
|
||||
#endif
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
template<> struct type_check_arithmetic<unsigned long long int> { typedef type_arithm_integral type; };
|
||||
#endif
|
||||
template<> struct type_check_arithmetic<long long int> { typedef type_arithm_integral type; };
|
||||
template<> struct type_check_arithmetic<unsigned long long int> { typedef type_arithm_integral type; };
|
||||
|
||||
template<> struct type_check_arithmetic<double> { typedef type_arithm_floating_point type; };
|
||||
template<> struct type_check_arithmetic<float> { typedef type_arithm_floating_point type; };
|
||||
@@ -86,12 +82,8 @@ template<> struct type_check_category<int> { typedef type_cat_int type; };
|
||||
template<> struct type_check_category<unsigned int> { typedef type_cat_int type; };
|
||||
template<> struct type_check_category<long int> { typedef type_cat_int type; };
|
||||
template<> struct type_check_category<unsigned long int> { typedef type_cat_int type; };
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
template<> struct type_check_category<long long int> { typedef type_cat_int type; };
|
||||
#endif
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
template<> struct type_check_category<unsigned long long int> { typedef type_cat_int type; };
|
||||
#endif
|
||||
template<> struct type_check_category<long long int> { typedef type_cat_int type; };
|
||||
template<> struct type_check_category<unsigned long long int> { typedef type_cat_int type; };
|
||||
|
||||
template<> struct type_check_category<double> { typedef type_cat_float type; };
|
||||
template<> struct type_check_category<float> { typedef type_cat_float type; };
|
||||
|
||||
@@ -85,12 +85,8 @@ TYPE_DEFINE_SPEC_0(type_is_integral, int, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_integral, unsigned int, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_integral, long, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_integral, unsigned long, true);
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
TYPE_DEFINE_SPEC_0(type_is_integral, long long, true);
|
||||
#endif
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
TYPE_DEFINE_SPEC_0(type_is_integral, unsigned long long, true);
|
||||
#endif
|
||||
TYPE_DEFINE_SPEC_0(type_is_integral, long long, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_integral, unsigned long long, true);
|
||||
|
||||
|
||||
template<typename T>
|
||||
@@ -100,9 +96,7 @@ TYPE_DEFINE_SPEC_0(type_is_signed, signed char, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_signed, short, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_signed, int, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_signed, long, true);
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
TYPE_DEFINE_SPEC_0(type_is_signed, long long, true);
|
||||
#endif
|
||||
TYPE_DEFINE_SPEC_0(type_is_signed, long long, true);
|
||||
|
||||
|
||||
template<typename T>
|
||||
@@ -112,9 +106,7 @@ TYPE_DEFINE_SPEC_0(type_is_unsigned, unsigned char, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_unsigned, unsigned short, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_unsigned, unsigned int, true);
|
||||
TYPE_DEFINE_SPEC_0(type_is_unsigned, unsigned long, true);
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
TYPE_DEFINE_SPEC_0(type_is_unsigned, unsigned long long, true);
|
||||
#endif
|
||||
TYPE_DEFINE_SPEC_0(type_is_unsigned, unsigned long long, true);
|
||||
|
||||
|
||||
template<typename T>
|
||||
@@ -336,9 +328,7 @@ template<> struct type_make_signed<unsigned char> { typedef signed char type; };
|
||||
template<> struct type_make_signed<unsigned short int> { typedef short int type; };
|
||||
template<> struct type_make_signed<unsigned int> { typedef int type; };
|
||||
template<> struct type_make_signed<unsigned long int> { typedef long int type; };
|
||||
#if !(defined DISABLE_ULL_INT && DISABLE_ULL_INT)
|
||||
template<> struct type_make_signed<unsigned long long int> { typedef long long int type; };
|
||||
#endif
|
||||
template<> struct type_make_signed<unsigned long long int> { typedef long long int type; };
|
||||
|
||||
|
||||
// list signed types
|
||||
@@ -348,9 +338,7 @@ template<> struct type_make_unsigned<signed char> { typedef unsigned char type;
|
||||
template<> struct type_make_unsigned<short int> { typedef unsigned short int type; };
|
||||
template<> struct type_make_unsigned<int> { typedef unsigned int type; };
|
||||
template<> struct type_make_unsigned<long int> { typedef unsigned long int type; };
|
||||
#if !(defined DISABLE_LL_INT && DISABLE_LL_INT)
|
||||
template<> struct type_make_unsigned<long long int> { typedef unsigned long long int type; };
|
||||
#endif
|
||||
template<> struct type_make_unsigned<long long int> { typedef unsigned long long int type; };
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
#include <sstream>
|
||||
#include <cstdarg> // std::va_start, va_list macro and friends
|
||||
|
||||
#include "hz/tls.h"
|
||||
#include "hz/string_sprintf.h" // string_vsprintf()
|
||||
#include "hz/exceptions.h" // THROW_FATAL
|
||||
|
||||
#include "dout.h"
|
||||
#include "dflags.h"
|
||||
@@ -44,7 +42,7 @@ std::ostream& debug_out(debug_level::flag level, const std::string& domain)
|
||||
}
|
||||
|
||||
// this is an internal error
|
||||
THROW_FATAL(debug_internal_error(msg.c_str()));
|
||||
throw debug_internal_error(msg.c_str());
|
||||
}
|
||||
|
||||
debug_internal::DebugState::level_map_t::iterator os = level_map->second.find(level);
|
||||
@@ -53,7 +51,7 @@ std::ostream& debug_out(debug_level::flag level, const std::string& domain)
|
||||
debug_level::get_name(level) + " in domain: \"" + domain + "\".";
|
||||
|
||||
// this is an internal error
|
||||
THROW_FATAL(debug_internal_error(msg.c_str()));
|
||||
throw debug_internal_error(msg.c_str());
|
||||
}
|
||||
|
||||
return *(os->second);
|
||||
|
||||
@@ -184,13 +184,8 @@ namespace debug_internal {
|
||||
|
||||
/// \def DBG_FUNC_NAME
|
||||
/// Function name (without classes / namespaces) only, e.g. "main", as const char*.
|
||||
#if defined HAVE_CXX___func__ && HAVE_CXX___func__
|
||||
#define DBG_FUNC_NAME __func__
|
||||
#elif defined HAVE_CXX___FUNCTION__ && HAVE_CXX___FUNCTION__
|
||||
#define DBG_FUNC_NAME __FUNCTION__
|
||||
#else
|
||||
#define DBG_FUNC_NAME "unknown"
|
||||
#endif
|
||||
#define DBG_FUNC_NAME __func__
|
||||
|
||||
|
||||
/// \def DBG_FUNC_PRNAME
|
||||
/// Function pretty name is the whole function prototype,
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
#include "hz/hz_config.h" // DEBUG_BUILD
|
||||
|
||||
#include "hz/exceptions.h" // THROW_FATAL
|
||||
|
||||
#include "dstate.h"
|
||||
#include "dflags.h"
|
||||
#include "dchannel.h"
|
||||
@@ -99,8 +97,8 @@ bool debug_register_domain(const std::string& domain)
|
||||
// copy the "default" domain - use it as a template
|
||||
DebugState::domain_map_t::iterator def_iter = dm.find("default");
|
||||
if (def_iter == dm.end()) {
|
||||
THROW_FATAL(debug_internal_error(("debug_register_domain(\"" + domain
|
||||
+ "\"): Domain \"default\" doesn't exist.").c_str()));
|
||||
throw debug_internal_error(("debug_register_domain(\"" + domain
|
||||
+ "\"): Domain \"default\" doesn't exist.").c_str());
|
||||
}
|
||||
|
||||
DebugState::level_map_t& def_level_map = def_iter->second;
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#include <stack>
|
||||
|
||||
#include "hz/intrusive_ptr.h"
|
||||
#include "hz/tls.h"
|
||||
#include "hz/exceptions.h" // THROW_FATAL
|
||||
|
||||
#include "dflags.h"
|
||||
#include "dstream.h"
|
||||
@@ -73,51 +71,37 @@ namespace debug_internal {
|
||||
/// Get current indentation level. This is function thread-safe.
|
||||
int get_indent_level() const
|
||||
{
|
||||
if (!indent_level_.get())
|
||||
indent_level_.reset(new int(0));
|
||||
return *indent_level_;
|
||||
return indent_level_;
|
||||
}
|
||||
|
||||
/// Set current indentation level. This is function thread-safe.
|
||||
void set_indent_level(int indent_level)
|
||||
{
|
||||
if (!indent_level_.get()) {
|
||||
indent_level_.reset(new int(indent_level));
|
||||
} else {
|
||||
*indent_level_ = indent_level;
|
||||
}
|
||||
indent_level_ = indent_level;
|
||||
}
|
||||
|
||||
/// Open a debug_begin() context. This is function thread-safe.
|
||||
void push_inside_begin(bool value = true)
|
||||
{
|
||||
if (!inside_begin_.get())
|
||||
inside_begin_.reset(new std::stack<bool>());
|
||||
inside_begin_->push(value);
|
||||
inside_begin_.push(value);
|
||||
}
|
||||
|
||||
/// Close a debug_begin() context. This is function thread-safe.
|
||||
bool pop_inside_begin()
|
||||
{
|
||||
if (!inside_begin_.get())
|
||||
inside_begin_.reset(new std::stack<bool>());
|
||||
|
||||
if (inside_begin_->empty())
|
||||
THROW_FATAL(debug_usage_error("DebugState::pop_inside_begin(): Begin / End stack underflow! Mismatched begin()/end()?"));
|
||||
bool val = inside_begin_->top();
|
||||
inside_begin_->pop();
|
||||
if (inside_begin_.empty())
|
||||
throw debug_usage_error("DebugState::pop_inside_begin(): Begin / End stack underflow! Mismatched begin()/end()?");
|
||||
bool val = inside_begin_.top();
|
||||
inside_begin_.pop();
|
||||
return val;
|
||||
}
|
||||
|
||||
/// Check if we're inside a debug_begin() context. This is function thread-safe.
|
||||
bool get_inside_begin() const
|
||||
{
|
||||
if (!inside_begin_.get())
|
||||
inside_begin_.reset(new std::stack<bool>());
|
||||
|
||||
if (inside_begin_->empty())
|
||||
if (inside_begin_.empty())
|
||||
return false;
|
||||
return inside_begin_->top();
|
||||
return inside_begin_.top();
|
||||
}
|
||||
|
||||
|
||||
@@ -139,8 +123,8 @@ namespace debug_internal {
|
||||
// We can't provide any manual cleanup, because the only one we can do
|
||||
// is in main thread, and it's already being done with the destructor.
|
||||
|
||||
mutable hz::thread_local_ptr<int> indent_level_; ///< Current indentation level
|
||||
mutable hz::thread_local_ptr<std::stack<bool> > inside_begin_; ///< True if inside debug_begin() / debug_end() block
|
||||
mutable int indent_level_ = 0; ///< Current indentation level
|
||||
mutable std::stack<bool> inside_begin_; ///< True if inside debug_begin() / debug_end() block
|
||||
|
||||
domain_map_t domain_map; ///< Domain / debug level mapping.
|
||||
|
||||
|
||||
@@ -54,9 +54,6 @@ namespace debug_internal {
|
||||
|
||||
void DebugStreamBuf::flush_to_channel()
|
||||
{
|
||||
if (!oss_.get()) // tls
|
||||
oss_.reset(new std::ostringstream());
|
||||
|
||||
debug_format::type flags = dos_->format_;
|
||||
bool is_first_line = false;
|
||||
if (get_debug_state().get_inside_begin()) {
|
||||
@@ -75,10 +72,10 @@ namespace debug_internal {
|
||||
for (; iter != dos_->channels_.end(); ++iter) {
|
||||
// send() locks the channel if needed
|
||||
(*iter)->send(dos_->level_, dos_->domain_, flags,
|
||||
get_debug_state().get_indent_level(), is_first_line, oss_->str());
|
||||
get_debug_state().get_indent_level(), is_first_line, oss_.str());
|
||||
}
|
||||
oss_->str(""); // clear the buffer
|
||||
oss_->clear(); // clear the flags
|
||||
oss_.str(""); // clear the buffer
|
||||
oss_.clear(); // clear the flags
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "hz/intrusive_ptr.h"
|
||||
#include "hz/tls.h"
|
||||
|
||||
#include "dflags.h"
|
||||
#include "dchannel.h"
|
||||
@@ -125,10 +124,7 @@ namespace debug_internal {
|
||||
/// Write contents if necessary.
|
||||
void write_char(char c)
|
||||
{
|
||||
if (!oss_.get())
|
||||
oss_.reset(new std::ostringstream());
|
||||
|
||||
*oss_ << c;
|
||||
oss_ << c;
|
||||
if (c == '\n') // send to channels on newline
|
||||
flush_to_channel();
|
||||
}
|
||||
@@ -143,10 +139,7 @@ namespace debug_internal {
|
||||
|
||||
DebugOutStream* dos_; ///< Debug output stream
|
||||
|
||||
// It's thread-local because it is not shared between different flows.
|
||||
// we can't provide any manual cleanup, because the only one we can do it
|
||||
// is in main thread, and it's already being done with the destructor.
|
||||
hz::thread_local_ptr<std::ostringstream> oss_; ///< A buffer for output storage.
|
||||
std::ostringstream oss_; ///< A buffer for output storage.
|
||||
|
||||
/// Disallow copying
|
||||
DebugStreamBuf(const DebugStreamBuf& from);
|
||||
@@ -257,19 +250,13 @@ namespace debug_internal {
|
||||
/// as the first one.
|
||||
bool get_is_first_line()
|
||||
{
|
||||
if (!is_first_line_.get())
|
||||
is_first_line_.reset(new bool(true));
|
||||
return *is_first_line_;
|
||||
return is_first_line_;
|
||||
}
|
||||
|
||||
/// Set whether we're on the first line of the output or not.
|
||||
void set_is_first_line(bool b)
|
||||
{
|
||||
if (!is_first_line_.get()) {
|
||||
is_first_line_.reset(new bool(b));
|
||||
} else {
|
||||
*is_first_line_ = b;
|
||||
}
|
||||
is_first_line_ = b;
|
||||
}
|
||||
|
||||
|
||||
@@ -289,10 +276,7 @@ namespace debug_internal {
|
||||
std::string domain_; ///< Domain of this stream
|
||||
debug_format::type format_; ///< Format flags
|
||||
|
||||
// It's thread-local because it is not shared between different flows.
|
||||
// we can't provide any manual cleanup, because the only one we can do
|
||||
// is in main thread, and it's already being done with the destructor.
|
||||
hz::thread_local_ptr<bool> is_first_line_; ///< Whether it's the first line of output or not
|
||||
bool is_first_line_ = true; ///< Whether it's the first line of output or not
|
||||
|
||||
channel_list_t channels_; ///< Channels that the output is sent to
|
||||
|
||||
|
||||
@@ -44,18 +44,7 @@ inline bool load_from_string(const std::string& str)
|
||||
|
||||
|
||||
|
||||
|
||||
/// \fn bool save_to_file(const std::string& file)
|
||||
/// Save the "/config" branch to a file. This function is thread-safe.
|
||||
/// This function is available only if \c RMN_SERIALIZE_AVAILABLE is 1.
|
||||
|
||||
/// \fn bool save_to_string(std::string& put_here)
|
||||
/// Save the "/config" branch to a string. This function is thread-safe.
|
||||
/// This function is available only if \c RMN_SERIALIZE_AVAILABLE is 1.
|
||||
|
||||
|
||||
#if defined RMN_SERIALIZE_AVAILABLE && RMN_SERIALIZE_AVAILABLE
|
||||
|
||||
inline bool save_to_file(const std::string& file)
|
||||
{
|
||||
ConfigLockPolicy::ScopedLock locker(RootHolder::mutex);
|
||||
@@ -64,6 +53,7 @@ inline bool save_to_file(const std::string& file)
|
||||
}
|
||||
|
||||
|
||||
/// Save the "/config" branch to a string. This function is thread-safe.
|
||||
inline bool save_to_string(std::string& put_here)
|
||||
{
|
||||
ConfigLockPolicy::ScopedLock locker(RootHolder::mutex);
|
||||
@@ -71,20 +61,6 @@ inline bool save_to_string(std::string& put_here)
|
||||
return rmn::serialize_node_to_string_recursive(get_config_branch(), put_here);
|
||||
}
|
||||
|
||||
#else // no save function
|
||||
|
||||
inline bool save_to_file(const std::string& file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline bool save_to_string(std::string& put_here)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,17 +13,10 @@
|
||||
#define RCONFIG_RCMAIN_H
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept> // std::runtime_error
|
||||
|
||||
#include "hz/hz_config.h" // DISABLE_RTTI, RMN_TYPE_TRACKING
|
||||
|
||||
// if there's RTTI or type tracking enabled
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI) \
|
||||
|| (defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING)
|
||||
#include <stdexcept> // std::runtime_error
|
||||
#endif
|
||||
|
||||
#include "hz/hz_config.h"
|
||||
#include "hz/sync.h"
|
||||
#include "hz/exceptions.h" // THROW_FATAL
|
||||
|
||||
#include "rmn/resource_node.h" // resource_node type
|
||||
#include "rmn/resource_data_any.h" // any_type data provider
|
||||
@@ -316,20 +309,16 @@ bool set_data(const std::string& path, T data)
|
||||
{
|
||||
ConfigLockPolicy::ScopedLock locker(RootHolder::mutex);
|
||||
|
||||
// Verify that the default's type matches T,
|
||||
// if there's RTTI or type tracking enabled.
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI) \
|
||||
|| (defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING)
|
||||
// Verify that the default's type matches T
|
||||
if (!node_t::is_abs_path(path)) {
|
||||
node_ptr def_node = get_default_node(path);
|
||||
if (def_node && !def_node->data_is_empty()) { // if exists and not empty
|
||||
// template is needed for gcc3.3
|
||||
if (!def_node->template data_is_type<T>())
|
||||
THROW_FATAL(std::runtime_error(std::string(
|
||||
"rconfig::set_data(): Error: Type mismatch between default and config value for \"") + path + "\"!"));
|
||||
throw std::runtime_error(std::string(
|
||||
"rconfig::set_data(): Error: Type mismatch between default and config value for \"") + path + "\"!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
node_ptr cnode = get_config_node(path, true); // auto-create. note that it still may fail.
|
||||
if (cnode)
|
||||
@@ -411,9 +400,6 @@ inline bool data_is_empty(const std::string& path)
|
||||
}
|
||||
|
||||
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI) \
|
||||
|| (defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING)
|
||||
|
||||
/// Check if data at path is of type \c T. If the path is relative, look in /config, then /default.
|
||||
/// This function works only if either RTTI or type tracking is enabled
|
||||
template<typename T> inline
|
||||
@@ -427,8 +413,6 @@ bool data_is_type(const std::string& path)
|
||||
return node->data_is_type<T>();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// Get data at path. If the path is relative, look in /config, then /default.
|
||||
@@ -457,7 +441,7 @@ T get_data(const std::string& path)
|
||||
|
||||
node_ptr node = get_node(path);
|
||||
if (!node)
|
||||
THROW_FATAL(rmn::no_such_node(path)); // no such node
|
||||
throw rmn::no_such_node(path); // no such node
|
||||
return node->get_data<T>();
|
||||
}
|
||||
|
||||
@@ -490,7 +474,7 @@ T convert_data(const std::string& path)
|
||||
|
||||
node_ptr node = get_node(path);
|
||||
if (!node)
|
||||
THROW_FATAL(rmn::no_such_node(path));
|
||||
throw rmn::no_such_node(path);
|
||||
return node->convert_data<T>();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,7 @@
|
||||
#include <string>
|
||||
#include <iosfwd> // std::ostream
|
||||
|
||||
#include "hz/exceptions.h" // THROW_FATAL
|
||||
#include "hz/any_type.h"
|
||||
#include "hz/hz_config.h" // DISABLE_RTTI, RMN_TYPE_TRACKING (global_macros.h)
|
||||
|
||||
#include "resource_data_types.h"
|
||||
#include "resource_exception.h"
|
||||
@@ -85,14 +83,6 @@ class ResourceDataAny {
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
ResourceDataAny()
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
: type_(T_EMPTY)
|
||||
#endif
|
||||
{ }
|
||||
|
||||
|
||||
/// Copy data from \c src node
|
||||
template<class T>
|
||||
bool copy_data_from(const T& src)
|
||||
@@ -101,9 +91,6 @@ class ResourceDataAny {
|
||||
return false;
|
||||
|
||||
data_ = src->data_;
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
type_ = src->get_type();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -119,9 +106,6 @@ class ResourceDataAny {
|
||||
void clear_data()
|
||||
{
|
||||
data_.clear();
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
type_ = T_EMPTY;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -130,9 +114,6 @@ class ResourceDataAny {
|
||||
inline bool set_data(T data)
|
||||
{
|
||||
data_ = data;
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
type_ = node_data_type_by_real<T>::type;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -141,48 +122,17 @@ class ResourceDataAny {
|
||||
inline bool set_data(const char* data)
|
||||
{
|
||||
data_ = std::string(data);
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
type_ = node_data_type_by_real<std::string>::type;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// \fn bool data_is_type() const
|
||||
/// Check whether data is of type \c T.
|
||||
/// This function is available only if either RTTI or type tracking is enabled.
|
||||
#if !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
template<typename T>
|
||||
inline bool data_is_type() const
|
||||
{
|
||||
// template is needed for gcc 3.3
|
||||
return data_.template is_type<T>(); // won't work without RTTI! If empty, reacts to void only.
|
||||
return data_.template is_type<T>();
|
||||
}
|
||||
#elif defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
template<typename T>
|
||||
inline bool data_is_type() const
|
||||
{
|
||||
return node_data_type_by_real<T>::type == type_;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
/// Check whether data is of type \c type.
|
||||
/// This function is available only if type tracking is enabled.
|
||||
inline bool data_is_type(node_data_type type) const
|
||||
{
|
||||
return type == type_;
|
||||
}
|
||||
|
||||
/// Get data type.
|
||||
/// This function is available only if type tracking is enabled.
|
||||
inline node_data_type get_type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/// Get data of type \c T.
|
||||
@@ -190,10 +140,6 @@ class ResourceDataAny {
|
||||
template<typename T>
|
||||
inline bool get_data(T& put_it_here) const
|
||||
{
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
if (node_data_type_by_real<T>::type != type_)
|
||||
return false;
|
||||
#endif
|
||||
return data_.get(put_it_here); // returns false if empty or invalid type
|
||||
}
|
||||
|
||||
@@ -205,18 +151,14 @@ class ResourceDataAny {
|
||||
T get_data() const
|
||||
{
|
||||
if (data_.empty())
|
||||
THROW_FATAL(empty_data_retrieval());
|
||||
throw empty_data_retrieval();
|
||||
|
||||
#if defined DISABLE_RTTI && defined RMN_TYPE_TRACKING
|
||||
if (node_data_type_by_real<T>::type != type_)
|
||||
THROW_FATAL(type_mismatch());
|
||||
#endif
|
||||
try {
|
||||
// template is needed for gcc 3.3
|
||||
return data_.template get<T>(); // won't work if empty or invalid type
|
||||
}
|
||||
catch (hz::bad_any_cast& e) { // convert any_type exception to rmn exception.
|
||||
THROW_CUSTOM_BAD_CAST(type_mismatch, data_.type(), typeid(T));
|
||||
throw type_mismatch(data_.type(), typeid(T));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,24 +182,15 @@ class ResourceDataAny {
|
||||
T convert_data() const
|
||||
{
|
||||
if (data_.empty())
|
||||
THROW_FATAL(empty_data_retrieval());
|
||||
throw empty_data_retrieval();
|
||||
|
||||
#if defined DISABLE_RTTI && defined RMN_TYPE_TRACKING
|
||||
node_data_type to = node_data_type_by_real<T>::type;
|
||||
|
||||
// any T_ type is ok except these:
|
||||
if (type_ == T_VOIDPTR || type_ == T_UNKNOWN
|
||||
|| to == T_VOIDPTR || to == T_UNKNOWN) {
|
||||
THROW_FATAL(type_convert_error());
|
||||
}
|
||||
#endif
|
||||
try {
|
||||
// Note: This throws only if RTTI is enabled.
|
||||
// template is needed for gcc 3.3
|
||||
return data_.template convert<T>(); // won't work if empty or invalid type
|
||||
}
|
||||
catch (hz::bad_any_cast& e) {
|
||||
THROW_CUSTOM_BAD_CAST(type_convert_error, data_.type(), typeid(T));
|
||||
throw type_convert_error(data_.type(), typeid(T));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,10 +212,6 @@ class ResourceDataAny {
|
||||
|
||||
hz::any_type data_; ///< The data
|
||||
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
node_data_type type_; ///< Type of the data
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -31,10 +31,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd> // std::ostream
|
||||
|
||||
#include "hz/type_properties.h" // type_is_same<>
|
||||
#include "hz/exceptions.h" // THROW_FATAL
|
||||
#include "hz/static_assert.h" // HZ_STATIC_ASSERT
|
||||
#include <type_traits>
|
||||
|
||||
#include "resource_data_types.h"
|
||||
#include "resource_exception.h"
|
||||
@@ -132,7 +129,7 @@ class ResourceDataOne {
|
||||
template<typename T>
|
||||
inline bool data_is_type() const
|
||||
{
|
||||
return !empty_ && hz::type_is_same<T, DataType>::value;
|
||||
return !empty_ && std::is_same_v<T, DataType>;
|
||||
}
|
||||
|
||||
|
||||
@@ -169,9 +166,9 @@ class ResourceDataOne {
|
||||
T get_data() const
|
||||
{
|
||||
// use static assertion - early compile-time error is better than runtime error.
|
||||
HZ_STATIC_ASSERT((hz::type_is_same<T, DataType>::value), rmn_type_mismatch);
|
||||
static_assert((std::is_same_v<T, DataType>), "rmn type mismatch");
|
||||
if (empty_)
|
||||
THROW_FATAL(empty_data_retrieval());
|
||||
throw empty_data_retrieval();
|
||||
return data_;
|
||||
}
|
||||
|
||||
@@ -191,7 +188,7 @@ class ResourceDataOne {
|
||||
T convert_data() const
|
||||
{
|
||||
if (empty_)
|
||||
THROW_FATAL(empty_data_retrieval());
|
||||
throw empty_data_retrieval();
|
||||
return static_cast<T>(data_);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,7 @@
|
||||
#define RMN_RESOURCE_DATA_TYPES_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "hz/hz_config.h" // DISABLE_RTTI, RMN_TYPE_TRACKING (global_macros.h)
|
||||
#include "hz/cstdint.h"
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +39,7 @@ namespace rmn {
|
||||
|
||||
|
||||
|
||||
/// Node data type, used mainly in \c RMN_TYPE_TRACKING.
|
||||
/// Node data type.
|
||||
/// Only serializable and some additional types are here.
|
||||
enum node_data_type {
|
||||
T_EMPTY, ///< Not really a type, but may be handy
|
||||
@@ -85,35 +83,7 @@ template<> struct node_data_type_by_real<void*> { static const node_data_type ty
|
||||
|
||||
|
||||
|
||||
|
||||
/// \fn node_data_type resource_node_get_type(intrusive_ptr<resource_node<Data> > node)
|
||||
/// Get node_data_type from rmn node. Const pointer overload.
|
||||
|
||||
/// \fn node_data_type resource_node_get_type(intrusive_ptr<const resource_node<Data> > node)
|
||||
/// Get node_data_type from rmn node.
|
||||
|
||||
|
||||
|
||||
#if defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING
|
||||
|
||||
template<class Data> inline
|
||||
node_data_type resource_node_get_type(intrusive_ptr<const resource_node<Data> > node)
|
||||
{
|
||||
return node->get_type();
|
||||
}
|
||||
|
||||
|
||||
template<class Data> inline
|
||||
node_data_type resource_node_get_type(intrusive_ptr<resource_node<Data> > node)
|
||||
{
|
||||
return resource_node_get_type(intrusive_ptr<const resource_node<Data> >(node));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#elif !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
|
||||
// RTTI version (slower)
|
||||
template<class Data> inline
|
||||
node_data_type resource_node_get_type(intrusive_ptr<const resource_node<Data> > node)
|
||||
{
|
||||
@@ -132,17 +102,6 @@ node_data_type resource_node_get_type(intrusive_ptr<const resource_node<Data> >
|
||||
return T_UNKNOWN;
|
||||
}
|
||||
|
||||
template<class Data> inline
|
||||
node_data_type resource_node_get_type(intrusive_ptr<resource_node<Data> > node)
|
||||
{
|
||||
return resource_node_get_type(intrusive_ptr<const resource_node<Data> >(node));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@ T resource_node<Data>::get_data_by_path(const std::string& path) const
|
||||
{
|
||||
node_ptr p = find_node(path);
|
||||
if (!p)
|
||||
THROW_FATAL(no_such_node(path));
|
||||
throw no_such_node(path);
|
||||
return p->template get_data<T>();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <locale> // std::locale::classic()
|
||||
|
||||
#include "hz/cstdint.h"
|
||||
#include "hz/hz_config.h" // DISABLE_RTTI, RMN_* (global_macros.h)
|
||||
#include "hz/hz_config.h" // RMN_* (global_macros.h)
|
||||
#include "hz/string_algo.h" // string_split(), string_trim(), string_trim_copy()
|
||||
#include "hz/string_num.h" // string_is_numeric(), number_to_string()
|
||||
#include "hz/bin2ascii_encoder.h"
|
||||
@@ -215,15 +215,6 @@ inline node_data_type node_data_type_from_string(const std::string& str)
|
||||
|
||||
|
||||
|
||||
// Serializer works only if type tracking or RTTI is enabled
|
||||
#if (defined RMN_TYPE_TRACKING && RMN_TYPE_TRACKING) \
|
||||
|| !(defined DISABLE_RTTI && DISABLE_RTTI)
|
||||
|
||||
/// Whether rmn serialization is available or not.
|
||||
// Serializer works only if type tracking or RTTI is enabled.
|
||||
#define RMN_SERIALIZE_AVAILABLE 1
|
||||
|
||||
|
||||
/// Serialize _one_ node data to string (one line).
|
||||
template<class Data> inline
|
||||
std::string serialize_node_data(intrusive_ptr<const resource_node<Data> > node)
|
||||
@@ -452,10 +443,6 @@ bool serialize_node_to_file_recursive(intrusive_ptr<resource_node<Data> > node,
|
||||
|
||||
|
||||
|
||||
#endif // defined RMN_TYPE_TRACKING || !defined DISABLE_RTTI
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------------- Loading
|
||||
|
||||
|
||||
@@ -35,31 +35,6 @@
|
||||
\file
|
||||
Include this file to use the whole rmn.
|
||||
Otherwise, include individual headers.
|
||||
|
||||
|
||||
Configuration macros:
|
||||
|
||||
RMN_TYPE_TRACKING to enable explicit data type tracking in
|
||||
resource_data providers.
|
||||
|
||||
Note: Either RTTI or RMN_TYPE_TRACKING must be enabled to
|
||||
be able to serialize the node data! (Loading the serialized data will still work).
|
||||
|
||||
Note: Type tracking allows you to track them only from a predefined
|
||||
set of types.
|
||||
|
||||
Type tracking and RTTI effects on resource_data_any:
|
||||
|
||||
Type tracking (RMN_TYPE_TRACKING):
|
||||
- Fast (one integer comparison when checking types).
|
||||
- One more member variable in each node.
|
||||
- All type checks are limited to predefined types.
|
||||
|
||||
RTTI (disabled through DISABLE_RTTI, otherwise always present):
|
||||
- Possibly slower (type checks are performed through std::type_info comparisons).
|
||||
- No additional member variables.
|
||||
- Can check any type, thus it's more reliable when working with
|
||||
non-predefined types.
|
||||
*/
|
||||
|
||||
|
||||
@@ -74,20 +49,10 @@ Resource manager library internal implementation helpers.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/// \def RMN_TYPE_TRACKING
|
||||
/// If 1, enables rmn runtime type tracking (to report type errors),
|
||||
/// useful if there's no RTTI available.
|
||||
|
||||
/// \def RMN_RESOURCE_NODE_DEBUG
|
||||
/// Define this to 1 to enable debug printing of resource node operations.
|
||||
|
||||
|
||||
// #ifndef RMN_TYPE_TRACKING
|
||||
// #define RMN_TYPE_TRACKING 0
|
||||
// #endif
|
||||
|
||||
|
||||
#include "resource_base.h" // needed for node
|
||||
#include "resource_node.h" // resource_node type
|
||||
#include "resource_exception.h" // exceptions thrown in critical situations
|
||||
|
||||
Reference in New Issue
Block a user