blob: 590da9b58e7a0a1981c63711ad30fb8b8c37c9c2 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +00002 * Copyright (c) 2016-2018 ARM Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
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
Anthony Barbier7068f992017-10-26 15:23:08 +010027#include <stdarg.h>
Georgios Pinitas3faea252017-10-30 14:13:50 +000028#include <string>
29
30namespace arm_compute
31{
Georgios Pinitasd8734b52017-12-22 15:27:52 +000032/** Ignores unused arguments
33 *
34 * @tparam T Argument types
Alex Gildayc357c472018-03-21 13:54:09 +000035 *
36 * @param[in] ... Ignored arguments
Georgios Pinitasd8734b52017-12-22 15:27:52 +000037 */
38template <typename... T>
39inline void ignore_unused(T &&...)
40{
41}
42
43/** Available error codes */
Georgios Pinitas3faea252017-10-30 14:13:50 +000044enum class ErrorCode
45{
46 OK, /**< No error */
47 RUNTIME_ERROR /**< Generic runtime error */
48};
49
Georgios Pinitas631c41a2017-12-06 11:53:03 +000050/** Status class */
51class Status
Georgios Pinitas3faea252017-10-30 14:13:50 +000052{
53public:
54 /** Default Constructor **/
Georgios Pinitas631c41a2017-12-06 11:53:03 +000055 Status()
56 : _code(ErrorCode::OK), _error_description(" ")
Georgios Pinitas3faea252017-10-30 14:13:50 +000057 {
58 }
59 /** Default Constructor
60 *
61 * @param error_status Error status.
Georgios Pinitas631c41a2017-12-06 11:53:03 +000062 * @param error_description (Optional) Error description if error_status is not valid.
Georgios Pinitas3faea252017-10-30 14:13:50 +000063 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000064 explicit Status(ErrorCode error_status, std::string error_description = " ")
65 : _code(error_status), _error_description(error_description)
Georgios Pinitas3faea252017-10-30 14:13:50 +000066 {
67 }
68 /** Allow instances of this class to be copy constructed */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000069 Status(const Status &) = default;
Georgios Pinitas3faea252017-10-30 14:13:50 +000070 /** Allow instances of this class to be move constructed */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000071 Status(Status &&) = default;
Georgios Pinitas3faea252017-10-30 14:13:50 +000072 /** Allow instances of this class to be copy assigned */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000073 Status &operator=(const Status &) = default;
Georgios Pinitas3faea252017-10-30 14:13:50 +000074 /** Allow instances of this class to be move assigned */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000075 Status &operator=(Status &&) = default;
Georgios Pinitas3faea252017-10-30 14:13:50 +000076 /** Explicit bool conversion operator
77 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +000078 * @return True if there is no error else false
Georgios Pinitas3faea252017-10-30 14:13:50 +000079 */
80 explicit operator bool() const noexcept
81 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +000082 return _code == ErrorCode::OK;
Georgios Pinitas3faea252017-10-30 14:13:50 +000083 }
84 /** Gets error code
85 *
86 * @return Error code.
87 */
88 ErrorCode error_code() const
89 {
90 return _code;
91 }
92 /** Gets error description if any
93 *
94 * @return Error description.
95 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000096 std::string error_description() const
Georgios Pinitas3faea252017-10-30 14:13:50 +000097 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +000098 return _error_description;
Georgios Pinitas3faea252017-10-30 14:13:50 +000099 }
100 /** Throws a runtime exception in case it contains a valid error status */
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000101 void throw_if_error() const
Georgios Pinitas3faea252017-10-30 14:13:50 +0000102 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000103 if(!bool(*this))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000104 {
105 internal_throw_on_error();
106 }
107 }
108
109private:
110 /** Internal throwing function */
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000111 [[noreturn]] void internal_throw_on_error() const;
Georgios Pinitas3faea252017-10-30 14:13:50 +0000112
113private:
114 ErrorCode _code;
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000115 std::string _error_description;
Georgios Pinitas3faea252017-10-30 14:13:50 +0000116};
117
Anthony Barbier7068f992017-10-26 15:23:08 +0100118/** Creates an error containing the error message from variable argument list
119 *
120 * @param[in] error_code Error code
121 * @param[in] function Function in which the error occurred.
122 * @param[in] file Name of the file where the error occurred.
123 * @param[in] line Line on which the error occurred.
124 * @param[in] msg Message to display before aborting.
125 * @param[in] args Variable argument list of the message.
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000126 *
127 * @return status containing the error
Anthony Barbier7068f992017-10-26 15:23:08 +0100128 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000129Status create_error_va_list(ErrorCode error_code, const char *function, const char *file, const int line, const char *msg, va_list args);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000130/** Creates an error containing the error message
131 *
132 * @param[in] error_code Error code
133 * @param[in] function Function in which the error occurred.
134 * @param[in] file Name of the file where the error occurred.
135 * @param[in] line Line on which the error occurred.
136 * @param[in] msg Message to display before aborting.
137 * @param[in] ... Variable number of arguments of the message.
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000138 *
139 * @return status containing the error
Georgios Pinitas3faea252017-10-30 14:13:50 +0000140 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000141Status create_error(ErrorCode error_code, const char *function, const char *file, const int line, const char *msg, ...);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000142/** Print an error message then throw an std::runtime_error
143 *
144 * @param[in] function Function in which the error occurred.
145 * @param[in] file Name of the file where the error occurred.
146 * @param[in] line Line on which the error occurred.
147 * @param[in] msg Message to display before aborting.
148 * @param[in] ... Variable number of arguments of the message.
149 */
150[[noreturn]] void error(const char *function, const char *file, const int line, const char *msg, ...);
151}
152/** To avoid unused variables warnings
153 *
154 * This is useful if for example a variable is only used
155 * in debug builds and generates a warning in release builds.
156 *
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000157 * @param[in] ... Variables which are unused.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000158 */
Georgios Pinitasd9eb2752018-04-03 13:44:29 +0100159#define ARM_COMPUTE_UNUSED(...) arm_compute::ignore_unused(__VA_ARGS__) // NOLINT
Georgios Pinitas3faea252017-10-30 14:13:50 +0000160
161/** Creates an error with a given message
162 *
163 * @param[in] error_code Error code.
164 * @param[in] ... Message to encapsulate.
165 */
166#define ARM_COMPUTE_CREATE_ERROR(error_code, ...) ::arm_compute::create_error(error_code, __func__, __FILE__, __LINE__, __VA_ARGS__) // NOLINT
167
168/** Creates an error on location with a given message
169 *
170 * @param[in] error_code Error code.
171 * @param[in] func Function in which the error occurred.
172 * @param[in] file File in which the error occurred.
173 * @param[in] line Line in which the error occurred.
174 * @param[in] ... Message to display before aborting.
175 */
176#define ARM_COMPUTE_CREATE_ERROR_LOC(error_code, func, file, line, ...) ::arm_compute::create_error(error_code, func, file, line, __VA_ARGS__) // NOLINT
177
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000178/** Checks if a status contains an error and returns it
Georgios Pinitas3faea252017-10-30 14:13:50 +0000179 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000180 * @param[in] status Status value to check
Georgios Pinitas3faea252017-10-30 14:13:50 +0000181 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000182#define ARM_COMPUTE_RETURN_ON_ERROR(status) \
183 do \
184 { \
185 if(!bool(status)) \
186 { \
187 return status; \
188 } \
Georgios Pinitas3faea252017-10-30 14:13:50 +0000189 } while(false)
190
191/** Checks if an error value is valid if not throws an exception with the error
192 *
193 * @param[in] error Error value to check.
194 */
195#define ARM_COMPUTE_THROW_ON_ERROR(error) \
196 error.throw_if_error();
197
198/** If the condition is true, an error is returned
199 *
200 * @param[in] cond Condition to evaluate.
201 * @param[in] ... Error description message
202 */
203#define ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, ...) \
204 do \
205 { \
206 if(cond) \
207 { \
208 return ARM_COMPUTE_CREATE_ERROR(arm_compute::ErrorCode::RUNTIME_ERROR, __VA_ARGS__); \
209 } \
210 } while(false)
211
212/** If the condition is true, an error is thrown
213 *
214 * @param[in] cond Condition to evaluate.
215 * @param[in] func Function in which the error occurred.
216 * @param[in] file File in which the error occurred.
217 * @param[in] line Line in which the error occurred.
218 * @param[in] ... Error description message.
219 */
220#define ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(cond, func, file, line, ...) \
221 do \
222 { \
223 if(cond) \
224 { \
225 return ARM_COMPUTE_CREATE_ERROR_LOC(arm_compute::ErrorCode::RUNTIME_ERROR, func, file, line, __VA_ARGS__); \
226 } \
227 } while(false)
228
229/** If the condition is true, an error is returned
230 *
231 * @param[in] cond Condition to evaluate
232 */
233#define ARM_COMPUTE_RETURN_ERROR_ON(cond) \
234 ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, #cond)
235
236/** If the condition is true, an error is returned
237 *
238 * @param[in] cond Condition to evaluate.
239 * @param[in] func Function in which the error occurred.
240 * @param[in] file File in which the error occurred.
241 * @param[in] line Line in which the error occurred.
242 */
243#define ARM_COMPUTE_RETURN_ERROR_ON_LOC(cond, func, file, line) \
244 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(cond, func, file, line, #cond)
245
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100246/** Print the given message then throw an std::runtime_error.
247 *
248 * @param[in] ... Message to display before aborting.
249 */
250#define ARM_COMPUTE_ERROR(...) ::arm_compute::error(__func__, __FILE__, __LINE__, __VA_ARGS__) // NOLINT
251
252/** Print the given message then throw an std::runtime_error.
253 *
254 * @param[in] func Function in which the error occurred.
255 * @param[in] file File in which the error occurred.
256 * @param[in] line Line in which the error occurred.
257 * @param[in] ... Message to display before aborting.
258 */
259#define ARM_COMPUTE_ERROR_LOC(func, file, line, ...) ::arm_compute::error(func, file, line, __VA_ARGS__) // NOLINT
260
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100261#ifdef ARM_COMPUTE_ASSERTS_ENABLED
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000262/** Checks if a status value is valid if not throws an exception with the error
Georgios Pinitas3faea252017-10-30 14:13:50 +0000263 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000264 * @param[in] status Status value to check.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000265 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000266#define ARM_COMPUTE_ERROR_THROW_ON(status) \
267 status.throw_if_error()
Georgios Pinitas3faea252017-10-30 14:13:50 +0000268
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100269/** If the condition is true, the given message is printed and an exception is thrown
270 *
271 * @param[in] cond Condition to evaluate.
272 * @param[in] ... Message to print if cond is false.
273 */
274#define ARM_COMPUTE_ERROR_ON_MSG(cond, ...) \
275 do \
276 { \
277 if(cond) \
278 { \
279 ARM_COMPUTE_ERROR(__VA_ARGS__); \
280 } \
281 } while(0)
282
283/** If the condition is true, the given message is printed and an exception is thrown
284 *
285 * @param[in] cond Condition to evaluate.
286 * @param[in] func Function in which the error occurred.
287 * @param[in] file File in which the error occurred.
288 * @param[in] line Line in which the error occurred.
289 * @param[in] ... Message to print if cond is false.
290 */
291#define ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, ...) \
292 do \
293 { \
294 if(cond) \
295 { \
296 ARM_COMPUTE_ERROR_LOC(func, file, line, __VA_ARGS__); \
297 } \
298 } while(0)
299
300/** If the condition is true, the given message is printed and an exception is thrown, otherwise value is returned
301 *
302 * @param[in] cond Condition to evaluate.
303 * @param[in] val Value to be returned.
304 * @param[in] msg Message to print if cond is false.
305 */
306#define ARM_COMPUTE_CONST_ON_ERROR(cond, val, msg) (cond) ? throw std::logic_error(msg) : val;
307#else /* ARM_COMPUTE_ASSERTS_ENABLED */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000308#define ARM_COMPUTE_ERROR_THROW_ON(status)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100309#define ARM_COMPUTE_ERROR_ON_MSG(cond, ...)
310#define ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, ...)
311#define ARM_COMPUTE_CONST_ON_ERROR(cond, val, msg) val
312#endif /* ARM_COMPUTE_ASSERTS_ENABLED */
313
314/** If the condition is true then an error message is printed and an exception thrown
315 *
Georgios Pinitas3faea252017-10-30 14:13:50 +0000316 * @param[in] cond Condition to evaluate.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100317 */
318#define ARM_COMPUTE_ERROR_ON(cond) \
319 ARM_COMPUTE_ERROR_ON_MSG(cond, #cond)
320
321/** If the condition is true then an error message is printed and an exception thrown
322 *
Georgios Pinitas3faea252017-10-30 14:13:50 +0000323 * @param[in] cond Condition to evaluate.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100324 * @param[in] func Function in which the error occurred.
325 * @param[in] file File in which the error occurred.
326 * @param[in] line Line in which the error occurred.
327 */
328#define ARM_COMPUTE_ERROR_ON_LOC(cond, func, file, line) \
329 ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, #cond)
330
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100331#endif /* __ARM_COMPUTE_ERROR_H__ */