blob: e254956ad78e5e8be6577a3e5781ab6b9268d22d [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{
Vidhya Sudhan Loganathan76c85642018-05-25 13:53:02 +010046 OK, /**< No error */
47 RUNTIME_ERROR, /**< Generic runtime error */
48 UNSUPPORTED_EXTENSION_USE /**< Unsupported extension used*/
Georgios Pinitas3faea252017-10-30 14:13:50 +000049};
50
Georgios Pinitas631c41a2017-12-06 11:53:03 +000051/** Status class */
52class Status
Georgios Pinitas3faea252017-10-30 14:13:50 +000053{
54public:
55 /** Default Constructor **/
Georgios Pinitas631c41a2017-12-06 11:53:03 +000056 Status()
57 : _code(ErrorCode::OK), _error_description(" ")
Georgios Pinitas3faea252017-10-30 14:13:50 +000058 {
59 }
60 /** Default Constructor
61 *
62 * @param error_status Error status.
Georgios Pinitas631c41a2017-12-06 11:53:03 +000063 * @param error_description (Optional) Error description if error_status is not valid.
Georgios Pinitas3faea252017-10-30 14:13:50 +000064 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000065 explicit Status(ErrorCode error_status, std::string error_description = " ")
66 : _code(error_status), _error_description(error_description)
Georgios Pinitas3faea252017-10-30 14:13:50 +000067 {
68 }
69 /** Allow instances of this class to be copy constructed */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000070 Status(const Status &) = default;
Georgios Pinitas3faea252017-10-30 14:13:50 +000071 /** Allow instances of this class to be move constructed */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000072 Status(Status &&) = default;
Georgios Pinitas3faea252017-10-30 14:13:50 +000073 /** Allow instances of this class to be copy assigned */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000074 Status &operator=(const Status &) = default;
Georgios Pinitas3faea252017-10-30 14:13:50 +000075 /** Allow instances of this class to be move assigned */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000076 Status &operator=(Status &&) = default;
Georgios Pinitas3faea252017-10-30 14:13:50 +000077 /** Explicit bool conversion operator
78 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +000079 * @return True if there is no error else false
Georgios Pinitas3faea252017-10-30 14:13:50 +000080 */
81 explicit operator bool() const noexcept
82 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +000083 return _code == ErrorCode::OK;
Georgios Pinitas3faea252017-10-30 14:13:50 +000084 }
85 /** Gets error code
86 *
87 * @return Error code.
88 */
89 ErrorCode error_code() const
90 {
91 return _code;
92 }
93 /** Gets error description if any
94 *
95 * @return Error description.
96 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +000097 std::string error_description() const
Georgios Pinitas3faea252017-10-30 14:13:50 +000098 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +000099 return _error_description;
Georgios Pinitas3faea252017-10-30 14:13:50 +0000100 }
101 /** Throws a runtime exception in case it contains a valid error status */
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000102 void throw_if_error() const
Georgios Pinitas3faea252017-10-30 14:13:50 +0000103 {
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000104 if(!bool(*this))
Georgios Pinitas3faea252017-10-30 14:13:50 +0000105 {
106 internal_throw_on_error();
107 }
108 }
109
110private:
111 /** Internal throwing function */
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000112 [[noreturn]] void internal_throw_on_error() const;
Georgios Pinitas3faea252017-10-30 14:13:50 +0000113
114private:
115 ErrorCode _code;
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000116 std::string _error_description;
Georgios Pinitas3faea252017-10-30 14:13:50 +0000117};
118
Anthony Barbier7068f992017-10-26 15:23:08 +0100119/** Creates an error containing the error message from variable argument list
120 *
121 * @param[in] error_code Error code
122 * @param[in] function Function in which the error occurred.
123 * @param[in] file Name of the file where the error occurred.
124 * @param[in] line Line on which the error occurred.
125 * @param[in] msg Message to display before aborting.
126 * @param[in] args Variable argument list of the message.
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000127 *
128 * @return status containing the error
Anthony Barbier7068f992017-10-26 15:23:08 +0100129 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000130Status 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 +0000131/** Creates an error containing the error message
132 *
133 * @param[in] error_code Error code
134 * @param[in] function Function in which the error occurred.
135 * @param[in] file Name of the file where the error occurred.
136 * @param[in] line Line on which the error occurred.
137 * @param[in] msg Message to display before aborting.
138 * @param[in] ... Variable number of arguments of the message.
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000139 *
140 * @return status containing the error
Georgios Pinitas3faea252017-10-30 14:13:50 +0000141 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000142Status create_error(ErrorCode error_code, const char *function, const char *file, const int line, const char *msg, ...);
Georgios Pinitas3faea252017-10-30 14:13:50 +0000143/** Print an error message then throw an std::runtime_error
144 *
145 * @param[in] function Function in which the error occurred.
146 * @param[in] file Name of the file where the error occurred.
147 * @param[in] line Line on which the error occurred.
148 * @param[in] msg Message to display before aborting.
149 * @param[in] ... Variable number of arguments of the message.
150 */
151[[noreturn]] void error(const char *function, const char *file, const int line, const char *msg, ...);
152}
153/** To avoid unused variables warnings
154 *
155 * This is useful if for example a variable is only used
156 * in debug builds and generates a warning in release builds.
157 *
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000158 * @param[in] ... Variables which are unused.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000159 */
Georgios Pinitasd9eb2752018-04-03 13:44:29 +0100160#define ARM_COMPUTE_UNUSED(...) arm_compute::ignore_unused(__VA_ARGS__) // NOLINT
Georgios Pinitas3faea252017-10-30 14:13:50 +0000161
162/** Creates an error with a given message
163 *
164 * @param[in] error_code Error code.
165 * @param[in] ... Message to encapsulate.
166 */
167#define ARM_COMPUTE_CREATE_ERROR(error_code, ...) ::arm_compute::create_error(error_code, __func__, __FILE__, __LINE__, __VA_ARGS__) // NOLINT
168
169/** Creates an error on location with a given message
170 *
171 * @param[in] error_code Error code.
172 * @param[in] func Function in which the error occurred.
173 * @param[in] file File in which the error occurred.
174 * @param[in] line Line in which the error occurred.
175 * @param[in] ... Message to display before aborting.
176 */
177#define ARM_COMPUTE_CREATE_ERROR_LOC(error_code, func, file, line, ...) ::arm_compute::create_error(error_code, func, file, line, __VA_ARGS__) // NOLINT
178
Vidhya Sudhan Loganathan3ca97862018-04-23 08:20:04 +0100179/** An error is returned with the given description.
180 *
181 * @param[in] ... Error description message.
182 */
183#define ARM_COMPUTE_RETURN_ERROR_MSG(...) \
184 do \
185 { \
186 return ARM_COMPUTE_CREATE_ERROR(arm_compute::ErrorCode::RUNTIME_ERROR, __VA_ARGS__); \
187 } while(false)
188
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000189/** Checks if a status contains an error and returns it
Georgios Pinitas3faea252017-10-30 14:13:50 +0000190 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000191 * @param[in] status Status value to check
Georgios Pinitas3faea252017-10-30 14:13:50 +0000192 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000193#define ARM_COMPUTE_RETURN_ON_ERROR(status) \
194 do \
195 { \
196 if(!bool(status)) \
197 { \
198 return status; \
199 } \
Georgios Pinitas3faea252017-10-30 14:13:50 +0000200 } while(false)
201
202/** Checks if an error value is valid if not throws an exception with the error
203 *
204 * @param[in] error Error value to check.
205 */
206#define ARM_COMPUTE_THROW_ON_ERROR(error) \
207 error.throw_if_error();
208
209/** If the condition is true, an error is returned
210 *
211 * @param[in] cond Condition to evaluate.
212 * @param[in] ... Error description message
213 */
214#define ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, ...) \
215 do \
216 { \
217 if(cond) \
218 { \
219 return ARM_COMPUTE_CREATE_ERROR(arm_compute::ErrorCode::RUNTIME_ERROR, __VA_ARGS__); \
220 } \
221 } while(false)
222
223/** If the condition is true, an error is thrown
224 *
225 * @param[in] cond Condition to evaluate.
226 * @param[in] func Function in which the error occurred.
227 * @param[in] file File in which the error occurred.
228 * @param[in] line Line in which the error occurred.
229 * @param[in] ... Error description message.
230 */
231#define ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(cond, func, file, line, ...) \
232 do \
233 { \
234 if(cond) \
235 { \
236 return ARM_COMPUTE_CREATE_ERROR_LOC(arm_compute::ErrorCode::RUNTIME_ERROR, func, file, line, __VA_ARGS__); \
237 } \
238 } while(false)
239
240/** If the condition is true, an error is returned
241 *
242 * @param[in] cond Condition to evaluate
243 */
244#define ARM_COMPUTE_RETURN_ERROR_ON(cond) \
245 ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, #cond)
246
247/** If the condition is true, an error is returned
248 *
249 * @param[in] cond Condition to evaluate.
250 * @param[in] func Function in which the error occurred.
251 * @param[in] file File in which the error occurred.
252 * @param[in] line Line in which the error occurred.
253 */
254#define ARM_COMPUTE_RETURN_ERROR_ON_LOC(cond, func, file, line) \
255 ARM_COMPUTE_RETURN_ERROR_ON_LOC_MSG(cond, func, file, line, #cond)
256
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100257/** Print the given message then throw an std::runtime_error.
258 *
259 * @param[in] ... Message to display before aborting.
260 */
261#define ARM_COMPUTE_ERROR(...) ::arm_compute::error(__func__, __FILE__, __LINE__, __VA_ARGS__) // NOLINT
262
263/** Print the given message then throw an std::runtime_error.
264 *
265 * @param[in] func Function in which the error occurred.
266 * @param[in] file File in which the error occurred.
267 * @param[in] line Line in which the error occurred.
268 * @param[in] ... Message to display before aborting.
269 */
270#define ARM_COMPUTE_ERROR_LOC(func, file, line, ...) ::arm_compute::error(func, file, line, __VA_ARGS__) // NOLINT
271
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100272#ifdef ARM_COMPUTE_ASSERTS_ENABLED
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000273/** Checks if a status value is valid if not throws an exception with the error
Georgios Pinitas3faea252017-10-30 14:13:50 +0000274 *
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000275 * @param[in] status Status value to check.
Georgios Pinitas3faea252017-10-30 14:13:50 +0000276 */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000277#define ARM_COMPUTE_ERROR_THROW_ON(status) \
278 status.throw_if_error()
Georgios Pinitas3faea252017-10-30 14:13:50 +0000279
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100280/** If the condition is true, the given message is printed and an exception is thrown
281 *
282 * @param[in] cond Condition to evaluate.
283 * @param[in] ... Message to print if cond is false.
284 */
285#define ARM_COMPUTE_ERROR_ON_MSG(cond, ...) \
286 do \
287 { \
288 if(cond) \
289 { \
290 ARM_COMPUTE_ERROR(__VA_ARGS__); \
291 } \
292 } while(0)
293
294/** If the condition is true, the given message is printed and an exception is thrown
295 *
296 * @param[in] cond Condition to evaluate.
297 * @param[in] func Function in which the error occurred.
298 * @param[in] file File in which the error occurred.
299 * @param[in] line Line in which the error occurred.
300 * @param[in] ... Message to print if cond is false.
301 */
302#define ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, ...) \
303 do \
304 { \
305 if(cond) \
306 { \
307 ARM_COMPUTE_ERROR_LOC(func, file, line, __VA_ARGS__); \
308 } \
309 } while(0)
310
311/** If the condition is true, the given message is printed and an exception is thrown, otherwise value is returned
312 *
313 * @param[in] cond Condition to evaluate.
314 * @param[in] val Value to be returned.
315 * @param[in] msg Message to print if cond is false.
316 */
317#define ARM_COMPUTE_CONST_ON_ERROR(cond, val, msg) (cond) ? throw std::logic_error(msg) : val;
318#else /* ARM_COMPUTE_ASSERTS_ENABLED */
Georgios Pinitas631c41a2017-12-06 11:53:03 +0000319#define ARM_COMPUTE_ERROR_THROW_ON(status)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100320#define ARM_COMPUTE_ERROR_ON_MSG(cond, ...)
321#define ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, ...)
322#define ARM_COMPUTE_CONST_ON_ERROR(cond, val, msg) val
323#endif /* ARM_COMPUTE_ASSERTS_ENABLED */
324
325/** If the condition is true then an error message is printed and an exception thrown
326 *
Georgios Pinitas3faea252017-10-30 14:13:50 +0000327 * @param[in] cond Condition to evaluate.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100328 */
329#define ARM_COMPUTE_ERROR_ON(cond) \
330 ARM_COMPUTE_ERROR_ON_MSG(cond, #cond)
331
332/** If the condition is true then an error message is printed and an exception thrown
333 *
Georgios Pinitas3faea252017-10-30 14:13:50 +0000334 * @param[in] cond Condition to evaluate.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100335 * @param[in] func Function in which the error occurred.
336 * @param[in] file File in which the error occurred.
337 * @param[in] line Line in which the error occurred.
338 */
339#define ARM_COMPUTE_ERROR_ON_LOC(cond, func, file, line) \
340 ARM_COMPUTE_ERROR_ON_LOC_MSG(cond, func, file, line, #cond)
341
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100342#endif /* __ARM_COMPUTE_ERROR_H__ */