ATLAS Offline Software
Loading...
Searching...
No Matches
MessageCheck.h File Reference

macros for messaging and checking status codes More...

#include <type_traits>
#include <AsgMessaging/MsgHelpers.h>
#include <AsgMessaging/StatusCode.h>
#include "CxxUtils/checker_macros.h"
#include "CxxUtils/normalizeFunctionName.h"
#include <atomic>
Include dependency graph for Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:

Go to the source code of this file.

Classes

struct  asg::CheckHelper< StatusCode >
struct  asg::CheckHelper< int >
struct  asg::CheckHelper< bool >
struct  asg::CheckHelper< T * >

Namespaces

namespace  asg
namespace  asg::detail

Macros

#define ANA_MSG_HEADER(NAME)
 for standalone code this creates a new message category
#define ASG_TOOLS_MSG_STREAM(NAME, TITLE)
#define ANA_MSG_SOURCE(NAME, TITLE)
 the source code part of ANA_MSG_SOURCE
#define MSGSTREAM_FNAME   ""
#define ASG_TOOLS_MSGSTREAM_FNAME   ""
#define ASG_TOOLS_MSGSTREAM_PREFIX   __FILE__ << ":" << __LINE__ << " (" << ASG_TOOLS_MSGSTREAM_FNAME << "): "
 Common prefix for the non-usual messages.
#define ANA_MSG_OPEN   (
#define ANA_MSG_CLOSE   )
#define ANA_MSG_LVL_SERIOUS(lvl, xmsg, ...)
 Macro used to print "serious" messages.
#define ANA_MSG_LVL_NOCHK(lvl, xmsg, ...)
 Macro used to print "regular" messages.
#define ANA_MSG_LVL(lvl, xmsg, ...)
 Macro used to print "protected" messages.
#define ANA_MSG_VERBOSE(xmsg, ...)
 Macro printing verbose messages.
#define ANA_MSG_DEBUG(xmsg, ...)
 Macro printing debug messages.
#define ANA_MSG_INFO(xmsg, ...)
 Macro printing info messages.
#define ANA_MSG_WARNING(xmsg, ...)
 Macro printing warning messages.
#define ANA_MSG_ERROR(xmsg, ...)
 Macro printing error messages.
#define ANA_MSG_FATAL(xmsg, ...)
 Macro printing fatal messages.
#define ANA_MSG_ALWAYS(xmsg, ...)
 Macro printing messages that should always appear.
#define ANA_CHECK_SET_TYPE(TYPE)
 set the type for ANA_CHECK to report failures
#define ANA_CHECK(EXP)
 check whether the given expression was successful
#define ANA_CHECK_THROW(EXP)
 check whether the given expression was successful, throwing an exception on failure

Typedefs

typedef StatusCode AsgToolsCheckResultType
 the return type used by ANA_CHECK

Functions

void asg::detail::throw_check_fail (const std::string &str)
 throw an error for a failed check

Detailed Description

macros for messaging and checking status codes

Author
Nils Krumnack

The core of this file is the macro ANA_CHECK. With it, a simple main might look like this:

int main ()
{
using namespace asg::msgUserCode;
return 0;
}
#define ANA_CHECK(EXP)
check whether the given expression was successful
#define ANA_CHECK_SET_TYPE(TYPE)
set the type for ANA_CHECK to report failures
int main()
Definition hello.cxx:18
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition Init.cxx:31

For the most part ANA_CHECK works just like ATH_CHECK, except it works for any kind of status code (and other things like bool). By default it will return a regular StatusCode object, but you can make it return a different type by specifying ANA_CHECK_SET_TYPE at the beginning of the function. In the example I use it to return an int instead.

Unfortunately the example will compile without that line, but it will not work as expected, i.e. when you return StatusCode::FAILURE it will convert to a value of 0, which the shell interprets as success. There is very little I can do about that from my side, as that is the intrinsic behavior of StatusCode itself. So it is very important that you remember to put that line in.

If you have a function that needs to indicate failure, but can't do so via a status code (e.g. a constructor) you can use the macro ANA_CHECK_THROW, which will throw an exception instead. However, where possible a status code is preferred.

If this is actually a unit test and you already had the chance to update it to GoogleTest, then there are also macros ASSERT_SUCCESS, ASSERT_FAILURE, EXPECT_SUCCESS and EXPECT_FAILURE defined that integrate with the GoogleTest reporting system.

The other thing needed in the above example is the using namespace line. This makes the standard messaging macros available in functions that are not member functions of a tool. Or almost: It works fine in RootCore, but for dual-use code you need to use ANA_MSG_* instead of ATH_MSG_* for sending messages yourself.

The msgUserCode category I used here is meant for things like main functions, etc. If you want to use this for other standalone functions you may consider making your own category (or indeed several). For that you put in one of your headers the line:

ANA_MSG_HEADER (msgMyCategory)
#define ANA_MSG_HEADER(NAME)
for standalone code this creates a new message category

and then in one of the source files:

ANA_MSG_SOURCE (msgMyCategory, "MyCategory")
#define ANA_MSG_SOURCE(NAME, TITLE)
the source code part of ANA_MSG_SOURCE

That way users get the chosen label as part of the messages. Plus they can actually set the message level separately for each category.

Definition in file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

Macro Definition Documentation

◆ ANA_CHECK

#define ANA_CHECK ( EXP)
Value:
{ const auto sc__ = EXP; \
typedef typename std::decay<decltype(sc__)>::type scType__; \
ANA_MSG_ERROR ("Failed to call \"{}\"", #EXP); \
return ::asg::CheckHelper<AsgToolsCheckResultType>::failureCode(); \
} }
#define unlikely(x)
this is an internal traits class for status codes used by the ANA_CHECK* macros

check whether the given expression was successful

This works like ATH_CHECK except it can handle all kinds of status codes, not just the regular ones. In particular the user can also set the type of the status code returned via ANA_CHECK_SET_TYPE

Definition at line 325 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

325#define ANA_CHECK(EXP) \
326 { const auto sc__ = EXP; \
327 typedef typename std::decay<decltype(sc__)>::type scType__; \
328 if (!::asg::CheckHelper<scType__>::isSuccess (sc__)) [[unlikely]] { \
329 ANA_MSG_ERROR ("Failed to call \"{}\"", #EXP); \
330 return ::asg::CheckHelper<AsgToolsCheckResultType>::failureCode(); \
331 } }

◆ ANA_CHECK_SET_TYPE

#define ANA_CHECK_SET_TYPE ( TYPE)
Value:
StatusCode AsgToolsCheckResultType
the return type used by ANA_CHECK
#define TYPE(CODE, TYP, IOTYP)

set the type for ANA_CHECK to report failures

normally ANA_CHECK will report failures via a StatusCode object, but this macro can be called inside a function to tell it to report via a different type.

Definition at line 315 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

315#define ANA_CHECK_SET_TYPE(TYPE) \
316 typedef TYPE AsgToolsCheckResultType;

◆ ANA_CHECK_THROW

#define ANA_CHECK_THROW ( EXP)
Value:
{ const auto sc__ = EXP; \
typedef typename std::decay<decltype(sc__)>::type scType__; \
ANA_MSG_ERROR ("Failed to call \"{}\", throwing exception", #EXP); \
::asg::detail::throw_check_fail (#EXP); \
} }

check whether the given expression was successful, throwing an exception on failure

This works like ANA_CHECK except it throws when an error occurs. This is meant for situations in which we perform a check inside a function that does not return a StatusCode.

Definition at line 340 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

340#define ANA_CHECK_THROW(EXP) \
341 { const auto sc__ = EXP; \
342 typedef typename std::decay<decltype(sc__)>::type scType__; \
343 if (!::asg::CheckHelper<scType__>::isSuccess (sc__)) [[unlikely]] { \
344 ANA_MSG_ERROR ("Failed to call \"{}\", throwing exception", #EXP); \
345 ::asg::detail::throw_check_fail (#EXP); \
346 } }

◆ ANA_MSG_ALWAYS

#define ANA_MSG_ALWAYS ( xmsg,
... )
Value:
ANA_MSG_LVL_NOCHK( MSG::ALWAYS, xmsg __VA_OPT__(, __VA_ARGS__) )
#define ANA_MSG_LVL_NOCHK(lvl, xmsg,...)
Macro used to print "regular" messages.

Macro printing messages that should always appear.

Definition at line 299 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

◆ ANA_MSG_CLOSE

#define ANA_MSG_CLOSE   )

◆ ANA_MSG_DEBUG

#define ANA_MSG_DEBUG ( xmsg,
... )
Value:
ANA_MSG_LVL( MSG::DEBUG, xmsg __VA_OPT__(, __VA_ARGS__) )
#define ANA_MSG_LVL(lvl, xmsg,...)
Macro used to print "protected" messages.

Macro printing debug messages.

Definition at line 289 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

◆ ANA_MSG_ERROR

#define ANA_MSG_ERROR ( xmsg,
... )
Value:
ANA_MSG_LVL_SERIOUS( MSG::ERROR, xmsg __VA_OPT__(, __VA_ARGS__) )
#define ANA_MSG_LVL_SERIOUS(lvl, xmsg,...)
Macro used to print "serious" messages.

Macro printing error messages.

Definition at line 295 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

◆ ANA_MSG_FATAL

#define ANA_MSG_FATAL ( xmsg,
... )
Value:
ANA_MSG_LVL_SERIOUS( MSG::FATAL, xmsg __VA_OPT__(, __VA_ARGS__) )

Macro printing fatal messages.

Definition at line 297 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

◆ ANA_MSG_HEADER

#define ANA_MSG_HEADER ( NAME)
Value:
namespace NAME { \
MsgStream& msg (); \
MsgStream& msg (MSG::Level level); \
bool msgLvl (MSG::Level lvl); \
void setMsgLevel (MSG::Level level); }
MsgStream & msg
Definition testRead.cxx:32

for standalone code this creates a new message category

The idea is that this provides a way to use the "standard" messaging macros in code that doesn't inherit from AsgTools. All you have to do is put

using namespace NAME;

at the beginning of a function and then you can use the messaging macros as if you were inside an AsgTool.

Or almost, in RootCore this works just fine, but in Athena ATH_MSG_* is defined slightly differently so that this won't work. To that end we are providing ANA_MSG_* macros that work with this, and in both RootCore and Athena. This way you can also use ATH_CHECK/ANA_CHECK in your code.

Besides allowing to use the standard messaging macros, you can also set the message level similar to how you'd do it for an AsgTool:

NAME::setMsgLevel (MSG::DEBUG);
See also
ANA_MSG_SOURCE

Definition at line 111 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

111#define ANA_MSG_HEADER(NAME) \
112 namespace NAME { \
113 MsgStream& msg (); \
114 MsgStream& msg (MSG::Level level); \
115 bool msgLvl (MSG::Level lvl); \
116 void setMsgLevel (MSG::Level level); }

◆ ANA_MSG_INFO

#define ANA_MSG_INFO ( xmsg,
... )
Value:
ANA_MSG_LVL_NOCHK( MSG::INFO, xmsg __VA_OPT__(, __VA_ARGS__) )

Macro printing info messages.

Definition at line 291 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

◆ ANA_MSG_LVL

#define ANA_MSG_LVL ( lvl,
xmsg,
... )
Value:
do { \
if( msg().level() <= lvl ) { \
ANA_MSG_LVL_NOCHK( lvl, xmsg __VA_OPT__(, __VA_ARGS__) ); \
} \
} while( 0 )

Macro used to print "protected" messages.

Definition at line 279 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

279#define ANA_MSG_LVL( lvl, xmsg, ... ) \
280 do { \
281 if( msg().level() <= lvl ) { \
282 ANA_MSG_LVL_NOCHK( lvl, xmsg __VA_OPT__(, __VA_ARGS__) ); \
283 } \
284 } while( 0 )

◆ ANA_MSG_LVL_NOCHK

#define ANA_MSG_LVL_NOCHK ( lvl,
xmsg,
... )
Value:
msg( lvl ) << __VA_OPT__(std::format ANA_MSG_OPEN ) xmsg __VA_OPT__ (, __VA_ARGS__ ANA_MSG_CLOSE) << endmsg
#define endmsg

Macro used to print "regular" messages.

Definition at line 275 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

275#define ANA_MSG_LVL_NOCHK( lvl, xmsg, ... ) \
276 msg( lvl ) << __VA_OPT__(std::format ANA_MSG_OPEN ) xmsg __VA_OPT__ (, __VA_ARGS__ ANA_MSG_CLOSE) << endmsg

◆ ANA_MSG_LVL_SERIOUS

#define ANA_MSG_LVL_SERIOUS ( lvl,
xmsg,
... )
Value:
msg( lvl ) << ASG_TOOLS_MSGSTREAM_PREFIX << __VA_OPT__(std::format ANA_MSG_OPEN ) xmsg __VA_OPT__ (, __VA_ARGS__ ANA_MSG_CLOSE) << endmsg
#define ASG_TOOLS_MSGSTREAM_PREFIX
Common prefix for the non-usual messages.

Macro used to print "serious" messages.

Definition at line 271 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

271#define ANA_MSG_LVL_SERIOUS( lvl, xmsg, ... ) \
272 msg( lvl ) << ASG_TOOLS_MSGSTREAM_PREFIX << __VA_OPT__(std::format ANA_MSG_OPEN ) xmsg __VA_OPT__ (, __VA_ARGS__ ANA_MSG_CLOSE) << endmsg

◆ ANA_MSG_OPEN

#define ANA_MSG_OPEN   (

◆ ANA_MSG_SOURCE

#define ANA_MSG_SOURCE ( NAME,
TITLE )
Value:
namespace NAME \
{ \
MsgStream& msg () \
{ \
ASG_TOOLS_MSG_STREAM (result, TITLE); \
return result; \
} \
\
MsgStream& msg (MSG::Level level) \
{ \
return msg() << level; \
} \
\
bool msgLvl (MSG::Level lvl) \
{ \
if (msg().level() <= lvl) \
{ \
msg() << lvl; \
return true; \
} else \
{ \
return false; \
} \
} \
\
void setMsgLevel (MSG::Level level) \
{ \
::asg::MsgHelpers::setPkgMsgLevel (TITLE, level); \
} \
}

the source code part of ANA_MSG_SOURCE

For every message category that you introduce via ANA_MSG_SOURCE you have to add this in one of your source files, to add the source code needed for its function implementations

Definition at line 131 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

131#define ANA_MSG_SOURCE(NAME,TITLE) \
132 namespace NAME \
133 { \
134 MsgStream& msg () \
135 { \
136 ASG_TOOLS_MSG_STREAM (result, TITLE); \
137 return result; \
138 } \
139 \
140 MsgStream& msg (MSG::Level level) \
141 { \
142 return msg() << level; \
143 } \
144 \
145 bool msgLvl (MSG::Level lvl) \
146 { \
147 if (msg().level() <= lvl) \
148 { \
149 msg() << lvl; \
150 return true; \
151 } else \
152 { \
153 return false; \
154 } \
155 } \
156 \
157 void setMsgLevel (MSG::Level level) \
158 { \
159 ::asg::MsgHelpers::setPkgMsgLevel (TITLE, level); \
160 } \
161 }

◆ ANA_MSG_VERBOSE

#define ANA_MSG_VERBOSE ( xmsg,
... )
Value:
ANA_MSG_LVL( MSG::VERBOSE, xmsg __VA_OPT__(, __VA_ARGS__) )

Macro printing verbose messages.

Definition at line 287 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

◆ ANA_MSG_WARNING

#define ANA_MSG_WARNING ( xmsg,
... )
Value:
ANA_MSG_LVL_NOCHK( MSG::WARNING, xmsg __VA_OPT__(, __VA_ARGS__) )

Macro printing warning messages.

Definition at line 293 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

◆ ASG_TOOLS_MSG_STREAM

#define ASG_TOOLS_MSG_STREAM ( NAME,
TITLE )
Value:
static thread_local MsgStream NAME {::asg::MsgHelpers::pkgMsgStream (TITLE)};
static MsgStream & pkgMsgStream(const std::string &package)
the message stream for the given package identifier

Definition at line 122 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

122#define ASG_TOOLS_MSG_STREAM(NAME,TITLE) \
123 static thread_local MsgStream NAME {::asg::MsgHelpers::pkgMsgStream (TITLE)};

◆ ASG_TOOLS_MSGSTREAM_FNAME

#define ASG_TOOLS_MSGSTREAM_FNAME   ""

◆ ASG_TOOLS_MSGSTREAM_PREFIX

#define ASG_TOOLS_MSGSTREAM_PREFIX   __FILE__ << ":" << __LINE__ << " (" << ASG_TOOLS_MSGSTREAM_FNAME << "): "

Common prefix for the non-usual messages.

The idea is that a regular user usually only wants to see DEBUG, INFO and some WARNING messages. So those should be reasonably short. On the other hand serious warnings (ERROR, FATAL) messages should be as precise as possible to make debugging the issue easier.

Definition at line 264 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.

264#define ASG_TOOLS_MSGSTREAM_PREFIX \
265 __FILE__ << ":" << __LINE__ << " (" << ASG_TOOLS_MSGSTREAM_FNAME << "): "

◆ MSGSTREAM_FNAME

#define MSGSTREAM_FNAME   ""

Typedef Documentation

◆ AsgToolsCheckResultType

typedef StatusCode AsgToolsCheckResultType

the return type used by ANA_CHECK

this defaults to the regular StatusCode, but can be overriden via ANA_CHECK_SET_TYPE

Definition at line 307 of file Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h.