The Gaudi Framework  v30r3 (a5ef0a68)
StatusCode.h
Go to the documentation of this file.
1 #ifndef GAUDIKERNEL_STATUSCODE_H
2 #define GAUDIKERNEL_STATUSCODE_H
3 
4 #include "boost/preprocessor/facilities/overload.hpp"
5 #include <ostream>
6 #include <type_traits>
7 #include <utility>
8 
9 #include "GaudiKernel/Kernel.h"
10 
11 template <typename T>
13 };
14 
51 class StatusCode final
52 {
53 public:
54  typedef unsigned long code_t;
55 
56  enum class ErrorCode : code_t { FAILURE = 0, SUCCESS = 1, RECOVERABLE = 2 };
57 
65  struct Category {
66  constexpr Category() noexcept = default;
67  virtual ~Category() {}
68 
70  virtual const char* name() const = 0;
71 
73  virtual std::string message( code_t code ) const { return "UNKNOWN(" + std::to_string( code ) + ")"; }
74 
77  virtual bool isSuccess( code_t code ) const { return code == static_cast<code_t>( ErrorCode::SUCCESS ); }
78 
80  virtual bool isRecoverable( code_t code ) const { return code == static_cast<code_t>( ErrorCode::RECOVERABLE ); }
81  };
82 
84  static const Category& default_category() noexcept;
85 
86  // Provide shorthands for default code values
87  constexpr const static auto SUCCESS = ErrorCode::SUCCESS;
88  constexpr const static auto FAILURE = ErrorCode::FAILURE;
89  constexpr const static auto RECOVERABLE = ErrorCode::RECOVERABLE;
90 
92  StatusCode() = default;
93 
95  template <typename T, typename = typename std::enable_if<is_StatusCode_enum<T>::value>::type>
96  StatusCode( T sc, bool checked = false ) noexcept
97  {
98  *this = StatusCode( static_cast<StatusCode::code_t>( sc ), is_StatusCode_enum<T>::instance );
99  m_checked = checked;
100  }
101 
103  explicit StatusCode( code_t code, const StatusCode::Category& cat = default_category(),
104  bool checked = false ) noexcept
105  : m_cat( &cat ), m_code( code ), m_checked( checked )
106  {
107  }
108 
110  explicit StatusCode( code_t code, bool checked ) noexcept : StatusCode( code, default_category(), checked ) {}
111 
113  StatusCode( const StatusCode& rhs ) noexcept : m_cat( rhs.m_cat ), m_code( rhs.m_code ), m_checked( rhs.m_checked )
114  {
115  rhs.m_checked = true;
116  }
117 
119  StatusCode( StatusCode&& rhs ) noexcept : m_cat( rhs.m_cat ), m_code( rhs.m_code ), m_checked( rhs.m_checked )
120  {
121  rhs.m_checked = true;
122  }
123 
126  {
127  if ( UNLIKELY( s_checking ) ) check();
128  }
129 
130  StatusCode& operator=( const StatusCode& rhs ) noexcept
131  {
132  m_cat = rhs.m_cat;
133  m_code = rhs.m_code;
134  m_checked = std::exchange( rhs.m_checked, true );
135  return *this;
136  }
137 
138  bool isSuccess() const;
139  bool isFailure() const { return !isSuccess(); }
140  bool isRecoverable() const;
141 
143  explicit operator bool() const { return isSuccess(); }
144 
146  code_t getCode() const
147  {
148  m_checked = true;
149  return m_code;
150  }
151 
153  const StatusCode& setChecked( bool checked = true ) const
154  {
155  m_checked = checked;
156  return *this;
157  }
158  StatusCode& setChecked( bool checked = true )
159  {
160  m_checked = checked;
161  return *this;
162  }
163 
165  const StatusCode& ignore() const
166  {
167  setChecked( true );
168  return *this;
169  }
171  {
172  setChecked( true );
173  return *this;
174  }
175 
177  bool checked() const { return m_checked; }
178 
180  const StatusCode::Category& getCategory() const { return *m_cat; }
181 
183  std::string message() const { return getCategory().message( m_code ); }
184 
186  {
187  s << sc.message();
188  return s;
189  }
190 
194  friend bool operator==( const StatusCode& lhs, const StatusCode& rhs );
195  friend bool operator!=( const StatusCode& lhs, const StatusCode& rhs ) { return !( lhs == rhs ); }
196 
198  friend bool operator<( const StatusCode& lhs, const StatusCode& rhs )
199  {
200  lhs.m_checked = true;
201  rhs.m_checked = true;
202  return ( lhs.m_cat < rhs.m_cat || ( lhs.m_cat == rhs.m_cat && lhs.m_code < rhs.m_code ) );
203  }
204 
206  StatusCode& operator&=( const StatusCode& rhs );
207  StatusCode& operator|=( const StatusCode& rhs );
208 
209  static GAUDI_API void enableChecking();
210  static GAUDI_API void disableChecking();
211  static GAUDI_API bool checkingEnabled();
212 
228  {
229  bool m_enabled;
230 
231  public:
232  ScopedDisableChecking() : m_enabled( StatusCode::checkingEnabled() )
233  {
234  if ( m_enabled ) StatusCode::disableChecking();
235  }
237  {
238  if ( m_enabled ) StatusCode::enableChecking();
239  }
240  };
241 
242 private:
243  const Category* m_cat{&default_category()};
244  code_t m_code{static_cast<code_t>( ErrorCode::SUCCESS )};
245  mutable bool m_checked{false};
246  static bool s_checking;
247 
248  ErrorCode default_value() const;
249  void check();
250 };
251 
252 /*
253  * Macros to declare/implement StatusCode enums/categories
254  */
255 
258 #define STATUSCODE_ENUM_DECL( ENUM ) \
259  template <> \
260  struct is_StatusCode_enum<ENUM> : std::true_type { \
261  static const StatusCode::Category& instance; \
262  };
263 
267 #define STATUSCODE_ENUM_IMPL( ... ) BOOST_PP_OVERLOAD( STATUSCODE_ENUM_IMPL_, __VA_ARGS__ )( __VA_ARGS__ )
268 
269 #define STATUSCODE_ENUM_IMPL_1( ENUM ) \
270  const StatusCode::Category& is_StatusCode_enum<ENUM>::instance = StatusCode::default_category();
271 
272 #define STATUSCODE_ENUM_IMPL_2( ENUM, CATEGORY ) \
273  const StatusCode::Category& is_StatusCode_enum<ENUM>::instance = CATEGORY{};
274 
275 // Declare the default StatusCode enum
277 
278 /*
279  * Inline methods
280  */
281 
282 inline const StatusCode::Category& StatusCode::default_category() noexcept
283 {
285 }
286 
287 inline bool StatusCode::isSuccess() const
288 {
289  m_checked = true;
290  return ( m_code == static_cast<code_t>( ErrorCode::SUCCESS ) || m_cat->isSuccess( m_code ) );
291 }
292 
293 inline bool StatusCode::isRecoverable() const
294 {
295  m_checked = true;
296  return m_cat->isRecoverable( m_code );
297 }
298 
300 {
301  bool save_checked = m_checked; // Preserve checked status
302  auto r = isSuccess() ? ErrorCode::SUCCESS : ( isRecoverable() ? ErrorCode::RECOVERABLE : ErrorCode::FAILURE );
303  m_checked = save_checked;
304  return r;
305 }
306 
307 inline bool operator==( const StatusCode& lhs, const StatusCode& rhs )
308 {
309  lhs.m_checked = true;
310  rhs.m_checked = true;
311  return ( lhs.m_code == rhs.m_code ) &&
312  ( lhs.m_code == static_cast<StatusCode::code_t>( StatusCode::ErrorCode::SUCCESS ) ||
313  lhs.m_code == static_cast<StatusCode::code_t>( StatusCode::ErrorCode::FAILURE ) ||
314  ( lhs.m_cat == rhs.m_cat ) );
315 }
316 
318 {
319  // Ternary AND lookup matrix
320  static constexpr StatusCode::code_t AND[3][3] = {{0, 0, 0}, {0, 1, 2}, {0, 2, 2}};
321 
322  StatusCode::code_t l = static_cast<StatusCode::code_t>( default_value() );
323  StatusCode::code_t r = static_cast<StatusCode::code_t>( rhs.default_value() );
324  m_code = AND[l][r];
325  rhs.m_checked = true;
326  return *this;
327 }
328 
330 {
331  // Ternary OR lookup matrix
332  static constexpr StatusCode::code_t OR[3][3] = {{0, 1, 2}, {1, 1, 1}, {2, 1, 2}};
333 
334  StatusCode::code_t l = static_cast<StatusCode::code_t>( default_value() );
335  StatusCode::code_t r = static_cast<StatusCode::code_t>( rhs.default_value() );
336  m_code = OR[l][r];
337  rhs.m_checked = true;
338  return *this;
339 }
340 
342 inline StatusCode operator&( StatusCode lhs, const StatusCode& rhs ) { return lhs &= rhs; }
343 
345 inline StatusCode operator|( StatusCode lhs, const StatusCode& rhs ) { return lhs |= rhs; }
346 
348 inline bool& operator&=( bool& lhs, const StatusCode& sc ) { return lhs &= sc.isSuccess(); }
349 
351 inline bool& operator|=( bool& lhs, const StatusCode& sc ) { return lhs |= sc.isSuccess(); }
352 
353 #endif // GAUDIKERNEL_STATUSCODE_H
#define UNLIKELY(x)
Definition: Kernel.h:122
StatusCode operator|(StatusCode lhs, const StatusCode &rhs)
Ternary OR operator.
Definition: StatusCode.h:345
code_t m_code
The status code value.
Definition: StatusCode.h:244
friend bool operator<(const StatusCode &lhs, const StatusCode &rhs)
Comparison (values are grouped by category first)
Definition: StatusCode.h:198
bool checked() const
Has the StatusCode been checked?
Definition: StatusCode.h:177
bool isSuccess() const
Definition: StatusCode.h:287
bool m_checked
If the StatusCode has been checked.
Definition: StatusCode.h:245
The category assigned to a StatusCode.
Definition: StatusCode.h:65
Category
integration category
Definition: Integration.h:26
StatusCode & operator=(const StatusCode &rhs) noexcept
Definition: StatusCode.h:130
T to_string(T...args)
StatusCode(code_t code, const StatusCode::Category &cat=default_category(), bool checked=false) noexcept
Constructor from code_t in the default category (explicit conversion only)
Definition: StatusCode.h:103
virtual bool isSuccess(code_t code) const
Is code considered success ?
Definition: StatusCode.h:77
#define STATUSCODE_ENUM_DECL(ENUM)
Declare an enum to be used as StatusCode value.
Definition: StatusCode.h:258
const StatusCode & setChecked(bool checked=true) const
Check/uncheck StatusCode.
Definition: StatusCode.h:153
~StatusCode()
Destructor.
Definition: StatusCode.h:125
StatusCode(code_t code, bool checked) noexcept
Constructor from code_t and category (explicit conversion only)
Definition: StatusCode.h:110
static GAUDI_API void enableChecking()
Definition: StatusCode.cpp:40
StatusCode(const StatusCode &rhs) noexcept
Copy constructor.
Definition: StatusCode.h:113
StatusCode & setChecked(bool checked=true)
Definition: StatusCode.h:158
bool isFailure() const
Definition: StatusCode.h:139
STL class.
friend std::ostream & operator<<(std::ostream &s, const StatusCode &sc)
Definition: StatusCode.h:185
StatusCode(T sc, bool checked=false) noexcept
Constructor from enum type (allowing implicit conversion)
Definition: StatusCode.h:96
virtual bool isRecoverable(code_t code) const
Is code considered recoverable ?
Definition: StatusCode.h:80
StatusCode & ignore()
Definition: StatusCode.h:170
virtual ~Category()
Definition: StatusCode.h:67
const StatusCode::Category & getCategory() const
Retrieve category (does not "check" the StatusCode)
Definition: StatusCode.h:180
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:51
friend bool operator!=(const StatusCode &lhs, const StatusCode &rhs)
Definition: StatusCode.h:195
Simple RAII class to ignore unchecked StatusCode instances in a scope.
Definition: StatusCode.h:227
StatusCode operator&(StatusCode lhs, const StatusCode &rhs)
Ternary AND operator.
Definition: StatusCode.h:342
static bool s_checking
Global flag to control if StatusCode need to be checked.
Definition: StatusCode.h:246
bool isRecoverable() const
Definition: StatusCode.h:293
dictionary l
Definition: gaudirun.py:440
bool operator==(const StatusCode &lhs, const StatusCode &rhs)
Definition: StatusCode.h:307
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:165
bool & operator|=(bool &lhs, const StatusCode &sc)
Boolean OR assignment operator.
Definition: StatusCode.h:351
ErrorCode default_value() const
Project onto the default StatusCode values.
Definition: StatusCode.h:299
string s
Definition: gaudirun.py:253
static GAUDI_API void disableChecking()
Definition: StatusCode.cpp:42
code_t getCode() const
Retrieve value ("checks" the StatusCode)
Definition: StatusCode.h:146
std::string message() const
Description (or name) of StatusCode value.
Definition: StatusCode.h:183
bool & operator&=(bool &lhs, const StatusCode &sc)
Boolean AND assignment operator.
Definition: StatusCode.h:348
StatusCode(StatusCode &&rhs) noexcept
Move constructor.
Definition: StatusCode.h:119
#define GAUDI_API
Definition: Kernel.h:104
STL class.
virtual std::string message(code_t code) const
Description for code within this category.
Definition: StatusCode.h:73
const Category * m_cat
The status code category.
Definition: StatusCode.h:243
StatusCode & operator|=(const StatusCode &rhs)
Ternary logic operator with RECOVERABLE being the "third" state.
Definition: StatusCode.h:329
StatusCode & operator&=(const StatusCode &rhs)
Ternary logic operator with RECOVERABLE being the "third" state.
Definition: StatusCode.h:317
unsigned long code_t
type of StatusCode value
Definition: StatusCode.h:54