First round of porting to C++17 and removing old code.

This commit is contained in:
Alexander Shaduri
2017-12-30 20:27:07 +00:00
parent 6e8628b1df
commit 02cfa33907
60 changed files with 190 additions and 2943 deletions
+25
View File
@@ -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
])
-60
View File
@@ -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>]],
-50
View File
@@ -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
View File
@@ -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)
# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
+1 -4
View File
@@ -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.
}
+1 -2
View File
@@ -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
}
-2
View File
@@ -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
-75
View File
@@ -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
+7 -8
View File
@@ -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 ;
+8 -8
View File
@@ -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");
+8 -11
View File
@@ -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)
+4 -23
View File
@@ -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)
+6 -24
View File
@@ -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;
}
+2 -16
View File
@@ -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); }
-6
View File
@@ -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
}
+2 -82
View File
@@ -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
+1 -9
View File
@@ -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__
-105
View File
@@ -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
/// @}
-100
View File
@@ -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;
}
/// @}
+4 -32
View File
@@ -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
};
-82
View File
@@ -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
/// @}
-50
View File
@@ -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.
+20 -68
View File
@@ -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
-24
View File
@@ -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;
}
+2 -2
View File
@@ -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);
}
}
-94
View File
@@ -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
/// @}
+2 -13
View File
@@ -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;
+3 -14
View File
@@ -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
-4
View File
@@ -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
+4 -5
View File
@@ -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;
}
-312
View File
@@ -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
-113
View File
@@ -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
+2 -2
View File
@@ -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)));
}
}
+15 -15
View File
@@ -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."));
}
-440
View File
@@ -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
/// @}
-104
View File
@@ -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
/// @}
-151
View File
@@ -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
/// @}
-122
View File
@@ -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
/// @}
-115
View File
@@ -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
/// @}
-106
View File
@@ -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;
}
+4 -12
View File
@@ -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; };
+6 -18
View File
@@ -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; };
+2 -4
View File
@@ -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);
+2 -7
View File
@@ -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,
+2 -4
View File
@@ -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;
+11 -27
View File
@@ -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.
+3 -6
View File
@@ -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
}
+5 -21
View File
@@ -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
+1 -25
View File
@@ -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
+7 -23
View File
@@ -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>();
}
+5 -76
View File
@@ -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
};
+5 -8
View File
@@ -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_);
}
+2 -43
View File
@@ -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
+1 -1
View File
@@ -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>();
}
+1 -14
View File
@@ -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
View File
@@ -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