Skip to content

Commit

Permalink
added methods to get active info,warning, and error handlers (#726)
Browse files Browse the repository at this point in the history
* added methods to get active info,warning, and error handlers

* fix extra changelog stuff

* you learn something new every day

* learning continues, but this time related to spelling

* add docs about accessing default handlers
  • Loading branch information
cyrush committed Mar 12, 2021
1 parent 6353066 commit 83ef572
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 19 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -9,6 +9,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
### Added

#### General
- Added `conduit::utils::info_handler()`, `conduit::utils::warning_handler()`, and `conduit::utils::error_handler()` methods, which provide access to the currently registered info, warning, and error handlers.
- Added DataType::index_t method. Creates a DataType instance that describes an `index_t`, which is an alias to either `int32`, or `int 64` controlled by the `CONDUIT_INDEX_32` compile time option.
- Added several more methods to Python DataType interface

Expand Down Expand Up @@ -472,7 +473,8 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
### Added
- Initial Open Source Release on GitHub

[Unreleased]: https://github.com/llnl/conduit/compare/v0.7.0...HEAD
[Unreleased]: https://github.com/llnl/conduit/compare/v0.7.1...HEAD
[0.7.1]: https://github.com/llnl/conduit/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/llnl/conduit/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/llnl/conduit/compare/v0.5.1...v0.6.0
[0.5.1]: https://github.com/llnl/conduit/compare/v0.5.0...v0.5.1
Expand Down
17 changes: 17 additions & 0 deletions src/docs/sphinx/tutorial_cpp_errors.rst
Expand Up @@ -80,3 +80,20 @@ The default handlers are part of the conduit::utils interface, so you can restor
:language: cpp
:dedent: 4

Accessing Current Handlers
--------------------------------

You can access the currently active handlers using the `conduit::utils::info_handler()`,
`conduit::utils::warning_handler()`, and `conduit::utils::error_handler()` methods.
Here is an example that shows how to save the current handlers, temporarily restore
the default handlers, execute an operation, and finally restore the saved handlers:

.. literalinclude:: ../../tests/docs/t_conduit_docs_tutorial_errors.cpp
:start-after: BEGIN_EXAMPLE("error_handlers_current_push_pop")
:end-before: END_EXAMPLE("error_handlers_current_push_pop")
:language: cpp
:dedent: 4




21 changes: 21 additions & 0 deletions src/libs/conduit/conduit_utils.cpp
Expand Up @@ -104,6 +104,13 @@ set_info_handler(void(*on_info)
conduit_on_info = on_info;
}

//-----------------------------------------------------------------------------
conduit_info_handler
info_handler()
{
return conduit_on_info;
}

//-----------------------------------------------------------------------------
void
handle_info(const std::string &msg,
Expand Down Expand Up @@ -140,6 +147,13 @@ set_warning_handler(void(*on_warning)
conduit_on_warning = on_warning;
}

//-----------------------------------------------------------------------------
conduit_warning_handler
warning_handler()
{
return conduit_on_warning;
}

//-----------------------------------------------------------------------------
void
handle_warning(const std::string &msg,
Expand Down Expand Up @@ -177,6 +191,13 @@ set_error_handler(void(*on_error)
conduit_on_error = on_error;
}

//-----------------------------------------------------------------------------
conduit_error_handler
error_handler()
{
return conduit_on_error;
}

//-----------------------------------------------------------------------------
void
handle_error(const std::string &msg,
Expand Down
61 changes: 43 additions & 18 deletions src/libs/conduit/conduit_utils.hpp
Expand Up @@ -164,7 +164,6 @@ class Node;
//-----------------------------------------------------------------------------
namespace utils
{

//-----------------------------------------------------------------------------
/// Primary interface used by the conduit API when an info message is issued
/// This simply dispatches the message to the currently configured info handler.
Expand All @@ -175,12 +174,11 @@ namespace utils
int line);

//-----------------------------------------------------------------------------
/// Allows other libraries to provide an alternate info message handler.
/// Info handler callback function type
//-----------------------------------------------------------------------------
void CONDUIT_API set_info_handler( void(*on_info)
(const std::string &,
typedef void(*conduit_info_handler)(const std::string &,
const std::string &,
int));
int);

//-----------------------------------------------------------------------------
/// Default info message handler, which prints the message to std::cout;
Expand All @@ -189,6 +187,16 @@ namespace utils
const std::string &file,
int line);

//-----------------------------------------------------------------------------
/// Allows other libraries to provide an alternate info message handler.
//-----------------------------------------------------------------------------
void CONDUIT_API set_info_handler(conduit_info_handler on_info);

//-----------------------------------------------------------------------------
/// Returns the active info message handler.
//-----------------------------------------------------------------------------
conduit_info_handler CONDUIT_API info_handler();

//-----------------------------------------------------------------------------
/// Primary interface used by the conduit API when a warning is issued.
/// This simply dispatches the warning to the currently configured warning handler.
Expand All @@ -199,12 +207,11 @@ namespace utils
int line);

//-----------------------------------------------------------------------------
/// Allows other libraries to provide an alternate warning handler.
/// Warning handler callback function type
//-----------------------------------------------------------------------------
void CONDUIT_API set_warning_handler( void(*on_error)
(const std::string &,
const std::string &,
int));
typedef void(*conduit_warning_handler)(const std::string &,
const std::string &,
int);

//-----------------------------------------------------------------------------
/// Default warning handler, which throws a conduit::Error exception.
Expand All @@ -213,6 +220,15 @@ namespace utils
const std::string &file,
int line);

//-----------------------------------------------------------------------------
/// Allows other libraries to provide an alternate warning handler.
//-----------------------------------------------------------------------------
void CONDUIT_API set_warning_handler(conduit_warning_handler on_warning);

//-----------------------------------------------------------------------------
/// Returns the active warning message handler.
//-----------------------------------------------------------------------------
conduit_warning_handler CONDUIT_API warning_handler();

//-----------------------------------------------------------------------------
/// Primary interface used by the conduit API when an error occurs.
Expand All @@ -223,20 +239,29 @@ namespace utils
const std::string &file,
int line);

//-----------------------------------------------------------------------------
/// Allows other libraries to provide an alternate error handler.
//-----------------------------------------------------------------------------
void CONDUIT_API set_error_handler( void(*on_error)
(const std::string &,
const std::string &,
int));

//-----------------------------------------------------------------------------
/// Default error handler, which throws a conduit::Error exception.
//-----------------------------------------------------------------------------
void CONDUIT_API default_error_handler(const std::string &msg,
const std::string &file,
int line);
//-----------------------------------------------------------------------------
/// Warning handler callback function type
//-----------------------------------------------------------------------------
typedef void(*conduit_error_handler)(const std::string &,
const std::string &,
int);

//-----------------------------------------------------------------------------
/// Allows other libraries to provide an alternate error handler.
//-----------------------------------------------------------------------------
void CONDUIT_API set_error_handler(conduit_error_handler on_error);

//-----------------------------------------------------------------------------
/// Returns the active warning message handler.
//-----------------------------------------------------------------------------
conduit_error_handler CONDUIT_API error_handler();


//-----------------------------------------------------------------------------
/// Helpers for common string splitting operations.
Expand Down
122 changes: 122 additions & 0 deletions src/tests/conduit/t_conduit_utils.cpp
Expand Up @@ -24,6 +24,10 @@ bool info_occured = false;
bool warning_occured = false;
bool error_occured = false;

bool other_info_occured = false;
bool other_warning_occured = false;
bool other_error_occured = false;

//-----------------------------------------------------------------------------
void
print_msg(const std::string &msg,
Expand Down Expand Up @@ -66,6 +70,38 @@ my_error_handler(const std::string &msg,
error_occured = true;
}

//-----------------------------------------------------------------------------
void
my_other_info_handler(const std::string &msg,
const std::string &file,
int line)
{
print_msg(msg,file,line);
other_info_occured = true;
}


//-----------------------------------------------------------------------------
void
my_other_warning_handler(const std::string &msg,
const std::string &file,
int line)
{
print_msg(msg,file,line);
other_warning_occured = true;
}

//-----------------------------------------------------------------------------
void
my_other_error_handler(const std::string &msg,
const std::string &file,
int line)
{
print_msg(msg,file,line);
other_error_occured = true;
}


//-----------------------------------------------------------------------------
TEST(conduit_utils, error_constructors)
{
Expand Down Expand Up @@ -148,6 +184,92 @@ TEST(conduit_utils, override_error)

}

//-----------------------------------------------------------------------------
TEST(conduit_utils, handler_defaults_are_the_defaults)
{
conduit::utils::conduit_info_handler on_info = conduit::utils::info_handler();
conduit::utils::conduit_info_handler on_info_default = conduit::utils::default_info_handler;
EXPECT_EQ(on_info,on_info_default);

conduit::utils::conduit_warning_handler on_warning = conduit::utils::warning_handler();
conduit::utils::conduit_warning_handler on_warning_default = conduit::utils::default_warning_handler;
EXPECT_EQ(on_warning,on_warning_default);

conduit::utils::conduit_error_handler on_error = conduit::utils::error_handler();
conduit::utils::conduit_error_handler on_error_default = conduit::utils::default_error_handler;
EXPECT_EQ(on_error,on_error_default);


EXPECT_NE(on_info,on_error);
EXPECT_NE(on_info,on_warning);

//
// NOTE: (Excerpt from "Adventures in fun with compilers")
// The default implementations of:
// conduit::utils::default_warning_handler
// and
// conduit::utils::default_error_handler
// are identical at the source level.
// On windows, we hit a case where the compiler understands this
// and low and behold there is only one copy!
//
// B/c of this we can't expect the following to hold:
// EXPECT_NE(on_error,on_warning);
//

}

//-----------------------------------------------------------------------------
TEST(conduit_utils, handler_defaults_push_pop)
{
// change to other handler
conduit::utils::set_info_handler(my_other_info_handler);
conduit::utils::set_warning_handler(my_other_warning_handler);
conduit::utils::set_error_handler(my_other_error_handler);

// ----------
// demo push / pop like swing to default
// ----------
conduit::utils::conduit_info_handler curr_on_info = conduit::utils::info_handler();
conduit::utils::conduit_warning_handler curr_on_warning = conduit::utils::warning_handler();
conduit::utils::conduit_error_handler curr_on_error = conduit::utils::error_handler();

// set to default
conduit::utils::set_info_handler(conduit::utils::default_info_handler);
conduit::utils::set_warning_handler(conduit::utils::default_warning_handler);
conduit::utils::set_error_handler(conduit::utils::default_error_handler);

EXPECT_THROW(utils::handle_warning("ERROR!",__FILE__,__LINE__),
conduit::Error);

// set to curr
conduit::utils::set_info_handler(curr_on_info);
conduit::utils::set_warning_handler(curr_on_warning);
conduit::utils::set_error_handler(curr_on_error);

EXPECT_FALSE(other_info_occured);
EXPECT_FALSE(other_warning_occured);
EXPECT_FALSE(other_error_occured);

utils::handle_info("INFO!",__FILE__,__LINE__);
utils::handle_warning("WARNING!",__FILE__,__LINE__);
utils::handle_error("ERROR!",__FILE__,__LINE__);

EXPECT_TRUE(other_info_occured);
EXPECT_TRUE(other_warning_occured);
EXPECT_TRUE(other_error_occured);


// back set to default (for other tests !!!!)
conduit::utils::set_info_handler(conduit::utils::default_info_handler);
conduit::utils::set_warning_handler(conduit::utils::default_warning_handler);
conduit::utils::set_error_handler(conduit::utils::default_error_handler);

}




//-----------------------------------------------------------------------------
TEST(conduit_utils, escape_special_chars)
{
Expand Down
19 changes: 19 additions & 0 deletions src/tests/docs/t_conduit_docs_tutorial_errors.cpp
Expand Up @@ -100,6 +100,25 @@ TEST(conduit_tutorial, error_handlers)
conduit::utils::set_warning_handler(conduit::utils::default_warning_handler);
conduit::utils::set_error_handler(conduit::utils::default_error_handler);
END_EXAMPLE("error_handlers_reset");

BEGIN_EXAMPLE("error_handlers_current_push_pop");
// store current handlers
conduit::utils::conduit_info_handler on_info = conduit::utils::info_handler();
conduit::utils::conduit_warning_handler on_warn = conduit::utils::warning_handler();
conduit::utils::conduit_error_handler on_error = conduit::utils::error_handler();

// temporarily restore default handlers
conduit::utils::set_info_handler(conduit::utils::default_info_handler);
conduit::utils::set_warning_handler(conduit::utils::default_warning_handler);
conduit::utils::set_error_handler(conduit::utils::default_error_handler);

// do something exciting ...

// done with excitement, reset to previously saved handlers
conduit::utils::set_info_handler(on_info);
conduit::utils::set_warning_handler(on_warn);
conduit::utils::set_error_handler(on_error);
END_EXAMPLE("error_handlers_current_push_pop");
}


Expand Down

0 comments on commit 83ef572

Please sign in to comment.