Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 
50 class StatusCode final {
51 public:
52  typedef unsigned long code_t;
53 
54  enum class ErrorCode : code_t { FAILURE = 0, SUCCESS = 1, RECOVERABLE = 2 };
55 
63  struct Category {
64  constexpr Category() noexcept = default;
65  virtual ~Category() {}
66 
68  virtual const char* name() const = 0;
69 
71  virtual std::string message( code_t code ) const { return "UNKNOWN(" + std::to_string( code ) + ")"; }
72 
75  virtual bool isSuccess( code_t code ) const { return code == static_cast<code_t>( ErrorCode::SUCCESS ); }
76 
78  virtual bool isRecoverable( code_t code ) const { return code == static_cast<code_t>( ErrorCode::RECOVERABLE ); }
79  };
80 
82  static const Category& default_category() noexcept;
83 
84  // Provide shorthands for default code values
85  constexpr const static auto SUCCESS = ErrorCode::SUCCESS;
86  constexpr const static auto FAILURE = ErrorCode::FAILURE;
87  constexpr const static auto RECOVERABLE = ErrorCode::RECOVERABLE;
88 
90  StatusCode() = default;
91 
93  template <typename T, typename = typename std::enable_if<is_StatusCode_enum<T>::value>::type>
94  StatusCode( T sc, bool checked = false ) noexcept {
95  *this = StatusCode( static_cast<StatusCode::code_t>( sc ), is_StatusCode_enum<T>::instance );
96  m_checked = checked;
97  }
98 
100  explicit StatusCode( code_t code, const StatusCode::Category& cat = default_category(),
101  bool checked = false ) noexcept
102  : m_cat( &cat ), m_code( code ), m_checked( checked ) {}
103 
105  explicit StatusCode( code_t code, bool checked ) noexcept : StatusCode( code, default_category(), checked ) {}
106 
108  StatusCode( const StatusCode& rhs ) noexcept : m_cat( rhs.m_cat ), m_code( rhs.m_code ), m_checked( rhs.m_checked ) {
109  rhs.m_checked = true;
110  }
111 
113  StatusCode( StatusCode&& rhs ) noexcept : m_cat( rhs.m_cat ), m_code( rhs.m_code ), m_checked( rhs.m_checked ) {
114  rhs.m_checked = true;
115  }
116 
119  if ( UNLIKELY( s_checking ) ) check();
120  }
121 
122  StatusCode& operator=( const StatusCode& rhs ) noexcept {
123  m_cat = rhs.m_cat;
124  m_code = rhs.m_code;
125  m_checked = std::exchange( rhs.m_checked, true );
126  return *this;
127  }
128 
129  bool isSuccess() const;
130  bool isFailure() const { return !isSuccess(); }
131  bool isRecoverable() const;
132 
134  explicit operator bool() const { return isSuccess(); }
135 
137  code_t getCode() const {
138  m_checked = true;
139  return m_code;
140  }
141 
143  const StatusCode& setChecked( bool checked = true ) const {
144  m_checked = checked;
145  return *this;
146  }
147  StatusCode& setChecked( bool checked = true ) {
148  m_checked = checked;
149  return *this;
150  }
151 
153  const StatusCode& ignore() const {
154  setChecked( true );
155  return *this;
156  }
158  setChecked( true );
159  return *this;
160  }
161 
163  bool checked() const { return m_checked; }
164 
166  const StatusCode::Category& getCategory() const { return *m_cat; }
167 
169  std::string message() const { return getCategory().message( m_code ); }
170 
172  s << sc.message();
173  return s;
174  }
175 
179  friend bool operator==( const StatusCode& lhs, const StatusCode& rhs );
180  friend bool operator!=( const StatusCode& lhs, const StatusCode& rhs ) { return !( lhs == rhs ); }
181 
183  friend bool operator<( const StatusCode& lhs, const StatusCode& rhs ) {
184  lhs.m_checked = true;
185  rhs.m_checked = true;
186  return ( lhs.m_cat < rhs.m_cat || ( lhs.m_cat == rhs.m_cat && lhs.m_code < rhs.m_code ) );
187  }
188 
190  StatusCode& operator&=( const StatusCode& rhs );
191  StatusCode& operator|=( const StatusCode& rhs );
192 
193  static GAUDI_API void enableChecking();
194  static GAUDI_API void disableChecking();
195  static GAUDI_API bool checkingEnabled();
196 
212  bool m_enabled;
213 
214  public:
215  ScopedDisableChecking() : m_enabled( StatusCode::checkingEnabled() ) {
216  if ( m_enabled ) StatusCode::disableChecking();
217  }
219  if ( m_enabled ) StatusCode::enableChecking();
220  }
221  };
222 
223 private:
224  const Category* m_cat{&default_category()};
225  code_t m_code{static_cast<code_t>( ErrorCode::SUCCESS )};
226  mutable bool m_checked{false};
227  static bool s_checking;
228 
229  ErrorCode default_value() const;
230  void check();
231 };
232 
233 /*
234  * Macros to declare/implement StatusCode enums/categories
235  */
236 
239 #define STATUSCODE_ENUM_DECL( ENUM ) \
240  template <> \
241  struct is_StatusCode_enum<ENUM> : std::true_type { \
242  static const StatusCode::Category& instance; \
243  };
244 
248 #define STATUSCODE_ENUM_IMPL( ... ) BOOST_PP_OVERLOAD( STATUSCODE_ENUM_IMPL_, __VA_ARGS__ )( __VA_ARGS__ )
249 
250 #define STATUSCODE_ENUM_IMPL_1( ENUM ) \
251  const StatusCode::Category& is_StatusCode_enum<ENUM>::instance = StatusCode::default_category();
252 
253 #define STATUSCODE_ENUM_IMPL_2( ENUM, CATEGORY ) \
254  const StatusCode::Category& is_StatusCode_enum<ENUM>::instance = CATEGORY{};
255 
256 // Declare the default StatusCode enum
258 
259 /*
260  * Inline methods
261  */
262 
263 inline const StatusCode::Category& StatusCode::default_category() noexcept {
265 }
266 
267 inline bool StatusCode::isSuccess() const {
268  m_checked = true;
269  return ( m_code == static_cast<code_t>( ErrorCode::SUCCESS ) || m_cat->isSuccess( m_code ) );
270 }
271 
272 inline bool StatusCode::isRecoverable() const {
273  m_checked = true;
274  return m_cat->isRecoverable( m_code );
275 }
276 
278  bool save_checked = m_checked; // Preserve checked status
279  auto r = isSuccess() ? ErrorCode::SUCCESS : ( isRecoverable() ? ErrorCode::RECOVERABLE : ErrorCode::FAILURE );
280  m_checked = save_checked;
281  return r;
282 }
283 
284 inline bool operator==( const StatusCode& lhs, const StatusCode& rhs ) {
285  lhs.m_checked = true;
286  rhs.m_checked = true;
287  return ( lhs.m_code == rhs.m_code ) &&
288  ( lhs.m_code == static_cast<StatusCode::code_t>( StatusCode::ErrorCode::SUCCESS ) ||
289  lhs.m_code == static_cast<StatusCode::code_t>( StatusCode::ErrorCode::FAILURE ) ||
290  ( lhs.m_cat == rhs.m_cat ) );
291 }
292 
294  // Ternary AND lookup matrix
295  static constexpr StatusCode::code_t AND[3][3] = {{0, 0, 0}, {0, 1, 2}, {0, 2, 2}};
296 
297  StatusCode::code_t l = static_cast<StatusCode::code_t>( default_value() );
298  StatusCode::code_t r = static_cast<StatusCode::code_t>( rhs.default_value() );
299  m_code = AND[l][r];
300  rhs.m_checked = true;
301  return *this;
302 }
303 
305  // Ternary OR lookup matrix
306  static constexpr StatusCode::code_t OR[3][3] = {{0, 1, 2}, {1, 1, 1}, {2, 1, 2}};
307 
308  StatusCode::code_t l = static_cast<StatusCode::code_t>( default_value() );
309  StatusCode::code_t r = static_cast<StatusCode::code_t>( rhs.default_value() );
310  m_code = OR[l][r];
311  rhs.m_checked = true;
312  return *this;
313 }
314 
316 inline StatusCode operator&( StatusCode lhs, const StatusCode& rhs ) { return lhs &= rhs; }
317 
319 inline StatusCode operator|( StatusCode lhs, const StatusCode& rhs ) { return lhs |= rhs; }
320 
322 inline bool& operator&=( bool& lhs, const StatusCode& sc ) { return lhs &= sc.isSuccess(); }
323 
325 inline bool& operator|=( bool& lhs, const StatusCode& sc ) { return lhs |= sc.isSuccess(); }
326 
327 #endif // GAUDIKERNEL_STATUSCODE_H
#define UNLIKELY(x)
Definition: Kernel.h:89
StatusCode operator|(StatusCode lhs, const StatusCode &rhs)
Ternary OR operator.
Definition: StatusCode.h:319
code_t m_code
The status code value.
Definition: StatusCode.h:225
friend bool operator<(const StatusCode &lhs, const StatusCode &rhs)
Comparison (values are grouped by category first)
Definition: StatusCode.h:183
bool checked() const
Has the StatusCode been checked?
Definition: StatusCode.h:163
bool isSuccess() const
Definition: StatusCode.h:267
bool m_checked
If the StatusCode has been checked.
Definition: StatusCode.h:226
The category assigned to a StatusCode.
Definition: StatusCode.h:63
Category
integration category
Definition: Integration.h:24
StatusCode & operator=(const StatusCode &rhs) noexcept
Definition: StatusCode.h:122
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:100
virtual bool isSuccess(code_t code) const
Is code considered success ?
Definition: StatusCode.h:75
#define STATUSCODE_ENUM_DECL(ENUM)
Declare an enum to be used as StatusCode value.
Definition: StatusCode.h:239
const StatusCode & setChecked(bool checked=true) const
Check/uncheck StatusCode.
Definition: StatusCode.h:143
~StatusCode()
Destructor.
Definition: StatusCode.h:118
StatusCode(code_t code, bool checked) noexcept
Constructor from code_t and category (explicit conversion only)
Definition: StatusCode.h:105
static GAUDI_API void enableChecking()
Definition: StatusCode.cpp:42
StatusCode(const StatusCode &rhs) noexcept
Copy constructor.
Definition: StatusCode.h:108
StatusCode & setChecked(bool checked=true)
Definition: StatusCode.h:147
bool isFailure() const
Definition: StatusCode.h:130
STL class.
friend std::ostream & operator<<(std::ostream &s, const StatusCode &sc)
Definition: StatusCode.h:171
StatusCode(T sc, bool checked=false) noexcept
Constructor from enum type (allowing implicit conversion)
Definition: StatusCode.h:94
virtual bool isRecoverable(code_t code) const
Is code considered recoverable ?
Definition: StatusCode.h:78
StatusCode & ignore()
Definition: StatusCode.h:157
virtual ~Category()
Definition: StatusCode.h:65
const StatusCode::Category & getCategory() const
Retrieve category (does not "check" the StatusCode)
Definition: StatusCode.h:166
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
friend bool operator!=(const StatusCode &lhs, const StatusCode &rhs)
Definition: StatusCode.h:180
Simple RAII class to ignore unchecked StatusCode instances in a scope.
Definition: StatusCode.h:211
StatusCode operator&(StatusCode lhs, const StatusCode &rhs)
Ternary AND operator.
Definition: StatusCode.h:316
static bool s_checking
Global flag to control if StatusCode need to be checked.
Definition: StatusCode.h:227
bool isRecoverable() const
Definition: StatusCode.h:272
dictionary l
Definition: gaudirun.py:517
bool operator==(const StatusCode &lhs, const StatusCode &rhs)
Definition: StatusCode.h:284
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:153
bool & operator|=(bool &lhs, const StatusCode &sc)
Boolean OR assignment operator.
Definition: StatusCode.h:325
ErrorCode default_value() const
Project onto the default StatusCode values.
Definition: StatusCode.h:277
string s
Definition: gaudirun.py:312
static GAUDI_API void disableChecking()
Definition: StatusCode.cpp:44
code_t getCode() const
Retrieve value ("checks" the StatusCode)
Definition: StatusCode.h:137
std::string message() const
Description (or name) of StatusCode value.
Definition: StatusCode.h:169
bool & operator&=(bool &lhs, const StatusCode &sc)
Boolean AND assignment operator.
Definition: StatusCode.h:322
StatusCode(StatusCode &&rhs) noexcept
Move constructor.
Definition: StatusCode.h:113
#define GAUDI_API
Definition: Kernel.h:71
STL class.
virtual std::string message(code_t code) const
Description for code within this category.
Definition: StatusCode.h:71
const Category * m_cat
The status code category.
Definition: StatusCode.h:224
StatusCode & operator|=(const StatusCode &rhs)
Ternary logic operator with RECOVERABLE being the "third" state.
Definition: StatusCode.h:304
StatusCode & operator&=(const StatusCode &rhs)
Ternary logic operator with RECOVERABLE being the "third" state.
Definition: StatusCode.h:293
unsigned long code_t
type of StatusCode value
Definition: StatusCode.h:52