• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016-2019, 2021 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>
ignore_unused(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 **/
Status()56     Status()
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 = " ")
_code(error_status)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      */
error_code()89     ErrorCode error_code() const
90     {
91         return _code;
92     }
93     /** Gets error description if any
94      *
95      * @return Error description.
96      */
error_description()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 */
throw_if_error()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 abandoning.
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 abandoning.
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 abandoning.
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 */
486