Compute Library
 20.05
Error.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2019 ARM Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef ARM_COMPUTE_ERROR_H
25 #define ARM_COMPUTE_ERROR_H
26 
27 #include <array>
28 #include <string>
29 
30 namespace arm_compute
31 {
32 /** Ignores unused arguments
33  *
34  * @tparam T Argument types
35  *
36  * @param[in] ... Ignored arguments
37  */
38 template <typename... T>
39 inline void ignore_unused(T &&...)
40 {
41 }
42 
43 /** Available error codes */
44 enum class ErrorCode
45 {
46  OK, /**< No error */
47  RUNTIME_ERROR, /**< Generic runtime error */
48  UNSUPPORTED_EXTENSION_USE /**< Unsupported extension used*/
49 };
50 
51 /** Status class */
52 class Status
53 {
54 public:
55  /** Default Constructor **/
57  : _code(ErrorCode::OK), _error_description(" ")
58  {
59  }
60  /** Default Constructor
61  *
62  * @param error_status Error status.
63  * @param error_description (Optional) Error description if error_status is not valid.
64  */
65  explicit Status(ErrorCode error_status, std::string error_description = " ")
66  : _code(error_status), _error_description(error_description)
67  {
68  }
69  /** Allow instances of this class to be copy constructed */
70  Status(const Status &) = default;
71  /** Allow instances of this class to be move constructed */
72  Status(Status &&) = default;
73  /** Allow instances of this class to be copy assigned */
74  Status &operator=(const Status &) = default;
75  /** Allow instances of this class to be move assigned */
76  Status &operator=(Status &&) = default;
77  /** Explicit bool conversion operator
78  *
79  * @return True if there is no error else false
80  */
81  explicit operator bool() const noexcept
82  {
83  return _code == ErrorCode::OK;
84  }
85  /** Gets error code
86  *
87  * @return Error code.
88  */
90  {
91  return _code;
92  }
93  /** Gets error description if any
94  *
95  * @return Error description.
96  */
97  std::string error_description() const
98  {
99  return _error_description;
100  }
101  /** Throws a runtime exception in case it contains a valid error status */
102  void throw_if_error() const
103  {
104  if(!bool(*this))
105  {
106  internal_throw_on_error();
107  }
108  }
109 
110 private:
111  /** Internal throwing function */
112  [[noreturn]] void internal_throw_on_error() const;
113 
114 private:
115  ErrorCode _code;
116  std::string _error_description;
117 };
118 
119 /** Creates an error containing the error message
120  *
121  * @param[in] error_code Error code
122  * @param[in] msg Message to display before aborting.
123  *
124  * @return status containing the error
125  */
126 Status create_error(ErrorCode error_code, std::string msg);
127 
128 /** Creates an error and the error message
129  *
130  * @param[in] error_code Error code
131  * @param[in] func Function in which the error occurred.
132  * @param[in] file File in which the error occurred.
133  * @param[in] line Line in which the error occurred.
134  * @param[in] msg Message to display before aborting.
135  *
136  * @return status containing the error
137  */
138 Status create_error_msg(ErrorCode error_code, const char *func, const char *file, int line, const char *msg);
139 /** Throw an std::runtime_error
140  *
141  * @param[in] err Error status
142  */
143 [[noreturn]] void throw_error(Status err);
144 }
145 /** To avoid unused variables warnings
146  *
147  * This is useful if for example a variable is only used
148  * in debug builds and generates a warning in release builds.
149  *
150  * @param[in] ... Variables which are unused.
151  */
152 #define ARM_COMPUTE_UNUSED(...) ::arm_compute::ignore_unused(__VA_ARGS__) // NOLINT
153 
154 /** Creates an error with a given message
155  *
156  * @param[in] error_code Error code.
157  * @param[in] msg Message to encapsulate.
158  */
159 #define ARM_COMPUTE_CREATE_ERROR(error_code, msg) arm_compute::create_error_msg(error_code, __func__, __FILE__, __LINE__, msg)
160 
161 /** Creates an error on location with a given message
162  *
163  * @param[in] error_code Error code.
164  * @param[in] func Function in which the error occurred.
165  * @param[in] file File in which the error occurred.
166  * @param[in] line Line in which the error occurred.
167  * @param[in] msg Message to display before aborting.
168  */
169 #define ARM_COMPUTE_CREATE_ERROR_LOC(error_code, func, file, line, msg) arm_compute::create_error_msg(error_code, func, file, line, msg)
170 
171 /** Creates an error on location with a given message. Accepts a message format
172  * and a variable list of arguments matching the format description.
173  *
174  * @param[in] error_code Error code.
175  * @param[in] func Function in which the error occurred.
176  * @param[in] file File in which the error occurred.
177  * @param[in] line Line in which the error occurred.
178  * @param[in] msg Error description message format.
179  * @param[in] ... List of arguments matching the format description.
180  */
181 #define ARM_COMPUTE_CREATE_ERROR_LOC_VAR(error_code, func, file, line, msg, ...) \
182  do \
183  { \
184  std::array<char, 512> out{ 0 }; \
185  int offset = snprintf(out.data(), out.size(), "in %s %s:%d: ", func, file, line); \
186  snprintf(out.data() + offset, out.size() - offset, msg, __VA_ARGS__); \
187  arm_compute::create_error(error_code, std::string(out.data())); \
188  } while(false)
189 
190 /** An error is returned with the given description.
191  *
192  * @param[in] ... Error description message.
193  */
194 #define ARM_COMPUTE_RETURN_ERROR_MSG(...) \
195  do \
196  { \
197  return ARM_COMPUTE_CREATE_ERROR(arm_compute::ErrorCode::RUNTIME_ERROR, __VA_ARGS__); \
198  } while(false)
199 
200 /** Checks if a status contains an error and returns it
201  *
202  * @param[in] status Status value to check
203  */
204 #define ARM_COMPUTE_RETURN_ON_ERROR(status) \
205  do \
206  { \
207  if(!bool(status)) \
208  { \
209  return status; \
210  } \
211  } while(false)
212 
213 /** Checks if an error value is valid if not throws an exception with the error
214  *
215  * @param[in] error Error value to check.
216  */
217 #define ARM_COMPUTE_THROW_ON_ERROR(error) \
218  error.throw_if_error();
219 
220 /** If the condition is true, an error is returned. Accepts a message format
221  * and a variable list of arguments matching the format description.
222  *
223  * @param[in] cond Condition to evaluate.
224  * @param[in] msg Error description message format.
225  * @param[in] ... List of arguments matching the format description.
226  */
227 #define ARM_COMPUTE_RETURN_ERROR_ON_MSG_VAR(cond, msg, ...) \
228  do \
229  { \
230  if(cond) \
231  { \
232  std::array<char, 512> out{ 0 }; \
233  int offset = snprintf(out.data(), out.size(), "in %s %s:%d: ", __func__, __FILE__, __LINE__); \
234  snprintf(out.data() + offset, out.size() - offset, msg, __VA_ARGS__); \
235  return arm_compute::create_error(arm_compute::ErrorCode::RUNTIME_ERROR, std::string(out.data())); \
236  } \
237  } while(false)
238 
239 /** If the condition is true, an error is returned
240  *
241  * @param[in] cond Condition to evaluate.
242  * @param[in] msg Error description message
243  */
244 #define ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, msg) \
245  do \
246  { \
247  if(cond) \
248  { \
249  return arm_compute::create_error_msg(arm_compute::ErrorCode::RUNTIME_ERROR, __func__, __FILE__, __LINE__, msg); \
250  } \
251  } while(false)
252 
253 /** If the condition is true, an error is thrown. Accepts a message format
254  * and a variable list of arguments matching the format description.
255  *
256  * @param[in] cond Condition to evaluate.
257  * @param[in] func Function in which the error occurred.
258  * @param[in] file File in which the error occurred.
259  * @param[in] line Line in which the error occurred.
260  * @param[in] msg Error description message format.
261  * @param[in] ... List of arguments matching the format description.
262  */
263 #define ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG_VAR(cond, func, file, line, msg, ...) \
264  do \
265  { \
266  if(cond) \
267  { \
268  std::array<char, 512> out{ 0 }; \
269  int offset = snprintf(out.data(), out.size(), "in %s %s:%d: ", func, file, line); \
270  snprintf(out.data() + offset, out.size() - offset, msg, __VA_ARGS__); \
271  return arm_compute::create_error(ErrorCode::RUNTIME_ERROR, std::string(out.data())); \
272  } \
273  } while(false)
274 
275 /** If the condition is true, an error is thrown.
276  *
277  * @param[in] cond Condition to evaluate.
278  * @param[in] func Function in which the error occurred.
279  * @param[in] file File in which the error occurred.
280  * @param[in] line Line in which the error occurred.
281  * @param[in] msg Message to display.
282  */
283 #define ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(cond, func, file, line, msg) \
284  do \
285  { \
286  if(cond) \
287  { \
288  return arm_compute::create_error_msg(ErrorCode::RUNTIME_ERROR, func, file, line, msg); \
289  } \
290  } while(false)
291 
292 /** If the condition is true, an error is returned
293  *
294  * @param[in] cond Condition to evaluate
295  */
296 #define ARM_COMPUTE_RETURN_ERROR_ON(cond) \
297  ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, #cond)
298 
299 /** If the condition is true, an error is returned
300  *
301  * @param[in] cond Condition to evaluate.
302  * @param[in] func Function in which the error occurred.
303  * @param[in] file File in which the error occurred.
304  * @param[in] line Line in which the error occurred.
305  */
306 #define ARM_COMPUTE_RETURN_ERROR_ON_LOC(cond, func, file, line) \
307  ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(cond, func, file, line, #cond)
308 
309 /** Print the given message then throw an std::runtime_error.
310  *
311  * @param[in] func Function in which the error occurred.
312  * @param[in] file File in which the error occurred.
313  * @param[in] line Line in which the error occurred.
314  * @param[in] msg Message to display.
315  */
316 #define ARM_COMPUTE_THROW_ERROR(func, file, line, msg) \
317  do \
318  { \
319  arm_compute::throw_error(arm_compute::create_error_msg(arm_compute::ErrorCode::RUNTIME_ERROR, func, file, line, msg)); \
320  } while(false)
321 
322 /** Print the given message then throw an std::runtime_error. Accepts a message format
323  * and a variable list of arguments matching the format description.
324  *
325  * @param[in] func Function in which the error occurred.
326  * @param[in] file File in which the error occurred.
327  * @param[in] line Line in which the error occurred.
328  * @param[in] msg Error description message format.
329  * @param[in] ... List of arguments matching the format description.
330  */
331 #define ARM_COMPUTE_THROW_ERROR_VAR(func, file, line, msg, ...) \
332  do \
333  { \
334  std::array<char, 512> out{ 0 }; \
335  int offset = snprintf(out.data(), out.size(), "in %s %s:%d: ", func, file, line); \
336  snprintf(out.data() + offset, out.size() - offset, msg, __VA_ARGS__); \
337  arm_compute::throw_error(arm_compute::Status(arm_compute::ErrorCode::RUNTIME_ERROR, std::string(out.data()))); \
338  } while(false)
339 
340 /** Print the given message then throw an std::runtime_error. Accepts a message format
341  * and a variable list of arguments matching the format description.
342  *
343  * @param[in] msg Error description message format.
344  * @param[in] ... List of arguments matching the format description.
345  */
346 #define ARM_COMPUTE_ERROR_VAR(msg, ...) ARM_COMPUTE_THROW_ERROR_VAR(__func__, __FILE__, __LINE__, msg, __VA_ARGS__)
347 
348 /** Print the given message then throw an std::runtime_error.
349  *
350  * @param[in] msg Message to display.
351  */
352 #define ARM_COMPUTE_ERROR(msg) ARM_COMPUTE_THROW_ERROR(__func__, __FILE__, __LINE__, msg)
353 
354 /** Print the given message then throw an std::runtime_error. Accepts a message format
355  * and a variable list of arguments matching the format description.
356  *
357  * @param[in] func Function in which the error occurred.
358  * @param[in] file File in which the error occurred.
359  * @param[in] line Line in which the error occurred.
360  * @param[in] msg Error description message format.
361  * @param[in] ... List of arguments matching the format description.
362  */
363 #define ARM_COMPUTE_ERROR_LOC_VAR(func, file, line, msg, ...) ARM_COMPUTE_THROW_ERROR_VAR(func, file, line, msg, __VA_ARGS__) // NOLINT
364 
365 /** Print the given message then throw an std::runtime_error.
366  *
367  * @param[in] func Function in which the error occurred.
368  * @param[in] file File in which the error occurred.
369  * @param[in] line Line in which the error occurred.
370  * @param[in] msg Message to display.
371  */
372 #define ARM_COMPUTE_ERROR_LOC(func, file, line, msg) ARM_COMPUTE_THROW_ERROR(func, file, line, msg) // NOLINT
373 
374 /** If the condition is true, the given message is printed and program exits
375  *
376  * @param[in] cond Condition to evaluate.
377  * @param[in] msg Message to display.
378  */
379 #define ARM_COMPUTE_EXIT_ON_MSG(cond, msg) \
380  do \
381  { \
382  if(cond) \
383  { \
384  ARM_COMPUTE_ERROR(msg); \
385  } \
386  } while(false)
387 
388 /** If the condition is true, the given message is printed and program exits. Accepts a message format
389  * and a variable list of arguments matching the format description.
390  *
391  * @param[in] cond Condition to evaluate.
392  * @param[in] msg Error description message format.
393  * @param[in] ... List of arguments matching the format description.
394  */
395 #define ARM_COMPUTE_EXIT_ON_MSG_VAR(cond, msg, ...) \
396  do \
397  { \
398  if(cond) \
399  { \
400  ARM_COMPUTE_ERROR_VAR(msg, __VA_ARGS__); \
401  } \
402  } while(false)
403 
404 #ifdef ARM_COMPUTE_ASSERTS_ENABLED
405 /** Checks if a status value is valid if not throws an exception with the error
406  *
407  * @param[in] status Status value to check.
408  */
409 #define ARM_COMPUTE_ERROR_THROW_ON(status) \
410  status.throw_if_error()
411 
412 /** If the condition is true, the given message is printed and an exception is thrown
413  *
414  * @param[in] cond Condition to evaluate.
415  * @param[in] msg Message to display.
416  */
417 #define ARM_COMPUTE_ERROR_ON_MSG(cond, msg) \
418  ARM_COMPUTE_EXIT_ON_MSG(cond, msg)
419 
420 /** If the condition is true, the given message is printed and an exception is thrown. Accepts a message format
421  * and a variable list of arguments matching the format description.
422  *
423  * @param[in] cond Condition to evaluate.
424  * @param[in] msg Error description message format.
425  * @param[in] ... List of arguments matching the format description.
426  */
427 #define ARM_COMPUTE_ERROR_ON_MSG_VAR(cond, msg, ...) \
428  ARM_COMPUTE_EXIT_ON_MSG_VAR(cond, msg, __VA_ARGS__)
429 
430 /** If the condition is true, the given message is printed and an exception is thrown.
431  *
432  * @param[in] cond Condition to evaluate.
433  * @param[in] func Function in which the error occurred.
434  * @param[in] file File in which the error occurred.
435  * @param[in] line Line in which the error occurred.
436  * @param[in] ... Message to print if cond is false.
437  */
438 #define ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, ...) \
439  do \
440  { \
441  if(cond) \
442  { \
443  ARM_COMPUTE_ERROR_LOC_VAR(func, file, line, __VA_ARGS__); \
444  } \
445  } while(false)
446 
447 /** If the condition is true, the given message is printed and an exception is thrown, otherwise value is returned
448  *
449  * @param[in] cond Condition to evaluate.
450  * @param[in] val Value to be returned.
451  * @param[in] msg Message to print if cond is false.
452  */
453 #define ARM_COMPUTE_CONST_ON_ERROR(cond, val, msg) (cond) ? throw std::logic_error(msg) : val;
454 #else /* ARM_COMPUTE_ASSERTS_ENABLED */
455 #define ARM_COMPUTE_ERROR_THROW_ON(status)
456 #define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
457 #define ARM_COMPUTE_ERROR_ON_MSG_VAR(cond, msg, ...)
458 #define ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, ...)
459 #define ARM_COMPUTE_CONST_ON_ERROR(cond, val, msg) val
460 #endif /* ARM_COMPUTE_ASSERTS_ENABLED */
461 
462 /** If the condition is true then an error message is printed and an exception thrown
463  *
464  * @param[in] cond Condition to evaluate.
465  */
466 #define ARM_COMPUTE_ERROR_ON(cond) \
467  ARM_COMPUTE_ERROR_ON_MSG(cond, #cond)
468 
469 /** If the condition is true then an error message is printed and an exception thrown
470  *
471  * @param[in] cond Condition to evaluate.
472  * @param[in] func Function in which the error occurred.
473  * @param[in] file File in which the error occurred.
474  * @param[in] line Line in which the error occurred.
475  */
476 #define ARM_COMPUTE_ERROR_ON_LOC(cond, func, file, line) \
477  ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, "%s", #cond)
478 
479 #ifndef ARM_COMPUTE_EXCEPTIONS_DISABLED
480 #define ARM_COMPUTE_THROW(ex) throw(ex)
481 #else /* ARM_COMPUTE_EXCEPTIONS_DISABLED */
482 #define ARM_COMPUTE_THROW(ex) (ex), std::abort()
483 #endif /* ARM_COMPUTE_EXCEPTIONS_DISABLED */
484 
485 #endif /* ARM_COMPUTE_ERROR_H */
Status create_error_msg(ErrorCode error_code, const char *func, const char *file, int line, const char *msg)
Creates an error and the error message.
Definition: Error.cpp:39
Status(ErrorCode error_status, std::string error_description=" ")
Default Constructor.
Definition: Error.h:65
Status class.
Definition: Error.h:52
Copyright (c) 2017-2020 ARM Limited.
void throw_error(Status err)
Throw an std::runtime_error.
Definition: Error.cpp:46
ErrorCode
Available error codes.
Definition: Error.h:44
Status & operator=(const Status &)=default
Allow instances of this class to be copy assigned.
void ignore_unused(T &&...)
Ignores unused arguments.
Definition: Error.h:39
void throw_if_error() const
Throws a runtime exception in case it contains a valid error status.
Definition: Error.h:102
Status create_error(ErrorCode error_code, std::string msg)
Creates an error containing the error message.
Definition: Error.cpp:34
Status()
Default Constructor.
Definition: Error.h:56
std::string error_description() const
Gets error description if any.
Definition: Error.h:97
ErrorCode error_code() const
Gets error code.
Definition: Error.h:89