notify.hpp

Tools to alert users of messages (including errors and warnings) in a consistent manner.

This file is part of Empirical, https://github.com/devosoft/Empirical Copyright (C) 2021-2025 Michigan State University MIT Software license; see doc/LICENSE.md

There are a handful of notification types to consider:

  • Message: A simple notification.

  • Verbose: Optional messages that can be activated by category.

  • Warning: Something looks suspicious, but is not technically a problem (don’t exit)

  • Error: Something has gone horribly wrong and is impossible to recover from (exit)

  • Exception: Something didn’t go the way we expected, but we can still recover (exit if not handled)

  • Debug: A simple notification that should only be printed when NDEBUG is not set (don’t exit)

These can be called as functions in the notify namespace with the appropriate name.

notify::Message(“The file ‘”, filename, “’ has successfully loaded.”); notify::Warning(“Unused variable: “, var_name);

Messages default to “standard out”; all of the other default to “standard error”. Handling of these notifications can all be overridden by either whole category or by specific tag.

All of these functions also have a Test* version where the first argument must be true for the notification to occur. For example:

notify::TestError(x > 10, “The value x must be <= 10, but x = “, x);

There are three possible recipients for all errors/warnings.

  • The end-user if the problem stems from inputs they provided to the executable.

  • The library user if the problem is due to mis-use of library functionality.

  • The library developers if something that should be impossible occurs.

These functions target the first group; developers should prefer asserts to ensure that supposedly “impossible” situations do not occur.

SHORTCUTS:

  • Alert(…) is a shortcut to notify::Warning(…)

NOTES:

  • Whenever possible, Exception() should be preferred over Error(). They are can be responded to or selectively disabled, rather than always automatically halting execution.

  • Warning() should ideally detail what should be done differently to avoid that warning.

Note

Status: ALPHA

Defines

INCLUDE_EMP_BASE_NOTIFY_HPP_GUARD

Functions

template<typename ...Ts>
static bool Alert(Ts... args)
template<typename ...Ts>
static bool CappedAlert(size_t cap, Ts... inputs)

A version of Alert that will cap how many times it can go off.

namespace notify

Typedefs

using id_t = std::string
using message_t = std::string
using except_data_t = std::any
using id_arg_t = const id_t&
using message_arg_t = const message_t&
using response_t = bool(id_arg_t, message_arg_t, except_data_t)
using exit_fun_t = std::function<void(int)>

Enums

enum class Type

Values:

enumerator MESSAGE
enumerator DEBUG
enumerator WARNING
enumerator ERROR
enumerator EXCEPTION
enumerator NUM_TYPES

Functions

static id_t NotifyTypeID(Type type)

Convert a type to a human-readable string.

static id_t ColorTypeID(Type type)

Convert a type to a human-readable string in COLOR.

static NotifyData &GetData()

Central call to obtain NotifyData singleton.

inline auto &MessageHandlers()
inline auto &DebugHandlers()
inline auto &WarningHandlers()
inline auto &ErrorHandlers()
static void AddExitHandler(exit_fun_t fun)
static void ClearExitHandlers()
static void ReplaceExitHandlers()
template<typename ...FUN_Ts>
static void ReplaceExitHandlers(exit_fun_t fun, FUN_Ts... extras)
static void Exit(int exit_code)

Generic exit handler that calls all of the provided functions.

template<typename ...Ts>
static bool Notify(Type type, Ts... args)

Generic Notification where type must be specified.

static void Pause()
static void Unpause()
template<typename ...Ts>
static bool Message(Ts... args)

Send out a regular notification.

template<typename ...Ts>
static bool Debug(Ts... args)

Send out a DEBUG notification.

template<typename ...Ts>
static bool Warning(Ts... args)

Send out a notification of a WARNING.

template<typename ...Ts>
static bool Error(Ts... args)

Send out a notification of an ERROR.

template<typename ...Ts>
static bool TestMessage(bool test, Ts... args)
template<typename ...Ts>
static bool TestDebug(bool test, Ts... args)
template<typename ...Ts>
static bool TestWarning(bool test, Ts... args)
template<typename ...Ts>
static bool TestError(bool test, Ts... args)
template<typename FUN_T>
static HandlerSet &AddHandler(id_arg_t id, FUN_T fun)

Add a handler for a particular exception type.

template<typename FUN_T>
static HandlerSet &AddHandler(FUN_T fun)

Add a generic exception handler.

static HandlerSet &Ignore(id_arg_t id)

Ignore exceptions of a specific type.

static void SetVerbose(std::string id, bool make_active = true)

Turn on a particular verbosity category.

template<typename ...Ts>
static bool Verbose(const std::string &id, Ts... args)

Send out a notification of an “verbose” message.

static bool Exception(id_arg_t id, message_arg_t message = "", except_data_t except_data = 0)

Send out a notification of an Exception.

template<typename ...Ts>
static bool TestException(bool test, Ts... args)
static const std::vector<ExceptInfo> &GetExceptions()

Retrieve a vector of ALL unresolved exceptions.

static ExceptInfo GetException(id_arg_t id)

Retrieve the first unresolved exception with a given id.

static size_t CountExceptions()

Return a total count of how many unresolved exceptions are left.

static size_t CountExceptions(id_arg_t id)

Return a total count of how many unresolved exceptions have a given id.

static bool HasExceptions()

Identify whether there are ANY unresolved exceptions.

static bool HasException(id_arg_t id)

Identify whether there are any unresolved exceptions with a given id.

static void ClearExceptions()

Remove all unresolved exceptions.

static void ClearException(id_arg_t id)

Remove first exception with a given id.

Variables

static constexpr size_t num_types = static_cast<size_t>(Type::NUM_TYPES)
struct ExceptInfo
#include <notify.hpp>

Information about an exception that has occurred.

Public Members

id_t id = "__NONE__"

Which exception was triggered?

message_t message = ""

A detailed message of this exception.

except_data_t data

Extra data needed to resolve this exception.

class HandlerSet
#include <notify.hpp>

Public Functions

inline bool GetExitOnFail() const
inline HandlerSet &SetExitOnFail(bool _exit = true)
inline bool Trigger(id_arg_t id, message_arg_t message, except_data_t except_data)

Trigger all handlers associated with a given ID.

inline bool Trigger(id_arg_t id, message_arg_t message)
inline bool Trigger(const ExceptInfo &info)
inline HandlerSet &Add(fun_t in)
inline HandlerSet &Add(fun_no_data_t in)
inline HandlerSet &Add(fun_msg_only_t in)
inline HandlerSet &Clear()
inline void Replace()

Replace all handlers with nothing (i.e., clear them)

template<typename ...FUN_Ts>
inline void Replace(fun_t in, FUN_Ts... extra)

Replace all handlers with the generic ones provided.

Private Types

using fun_t = std::function<response_t>
using fun_no_data_t = std::function<bool(id_arg_t, message_arg_t)>
using fun_msg_only_t = std::function<bool(message_arg_t)>

Private Members

std::vector<fun_t> handlers
bool exit_on_fail = false
struct NotifyData
#include <notify.hpp>

Statically stored data about current notifications.

Public Functions

inline HandlerSet &GetHandler(Type type)
inline NotifyData()

Public Members

std::unordered_map<id_t, HandlerSet> handler_map
std::unordered_map<std::string, bool> verbose_map
std::vector<exit_fun_t> exit_funs
std::vector<ExceptInfo> except_queue
std::vector<ExceptInfo> pause_queue
bool lethal_exceptions = true
bool is_paused = false

Public Static Functions

static inline void DefaultPrint(const std::string &msg, [[maybe_unused]] bool to_cerr = false)