1 /* 2 * Copyright (c) 2014-2017, Siemens AG. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #ifndef EMBB_BASE_EXCEPTIONS_H_ 28 #define EMBB_BASE_EXCEPTIONS_H_ 29 30 #ifdef EMBB_PLATFORM_COMPILER_MSVC 31 #pragma warning(push) 32 // Disable warning that exceptions are disabled but try/catch is used. 33 #pragma warning(disable : 4530) 34 #endif // EMBB_PLATFORM_COMPILER_MSVC 35 36 #include <string> 37 #include <exception> 38 39 #ifdef EMBB_PLATFORM_COMPILER_MSVC 40 #pragma warning(pop) 41 #endif 42 43 #include <embb/base/internal/cmake_config.h> 44 #include <embb/base/c/errors.h> 45 46 /** 47 * \defgroup CPP_BASE_EXCEPTIONS Exception 48 * 49 * Exception types. 50 * 51 * If exceptions are disabled, i.e., if the library was built without support 52 * for exceptions, no exceptions will be thrown. Instead, an error message is 53 * printed to \c stderr and the program exits with the code representing the 54 * exception. 55 * 56 * \ingroup CPP_BASE 57 */ 58 59 /** 60 * Macros to be used within EMBB when throwing and catching exceptions. 61 * 62 * Example: 63 * - Throwing an exception: 64 * EMBB_THROW(NoMemoryException, "Could not create thread."); 65 * --> If exceptions are disabled, this will write an error to stderr, 66 * containing the exception's message, and exit the program with the code 67 * of the exception. 68 * - Try/catch block: 69 * EMBB_TRY{ ... things to try ... } 70 * EMBB_CATCH(ExceptionXYZ& e){ ... things to catch ... } 71 * --> If exceptions are disabled, this will execute the try block without and 72 * replace the catch() statement by "if (false)", such that 73 * the catch block will be compiled but never executed. 74 */ 75 #ifdef EMBB_USE_EXCEPTIONS 76 #define EMBB_TRY try 77 #define EMBB_THROW(Type, Message) throw Type(Message); 78 #define EMBB_CATCH(Statement) catch(Statement) 79 #else /* EMBB_USE_EXCEPTIONS */ 80 #include <stdio.h> 81 #include <stdlib.h> 82 #include <embb/base/c/internal/unused.h> 83 #define EMBB_TRY 84 /** 85 * Concatenates the inputs. 86 */ 87 #define EMBB_CATCH_VAR_CAT2(X, Y) X##Y 88 /** 89 * Is a necessary intermediate macro to create EMBB_CATCH_VAR. 90 */ 91 #define EMBB_CATCH_VAR_CAT1(X, Y) EMBB_CATCH_VAR_CAT2(X, Y) 92 /** 93 * Defines a unique variable name for each line of code. 94 * 95 * The line number is concatenated to a base name. 96 */ 97 #define EMBB_CATCH_VAR EMBB_CATCH_VAR_CAT1(embb_catch_var_, __LINE__) 98 /** 99 * Replaces catch(xyz) by an if-statement that is always false. 100 * 101 * To avoid a compiler warning that the condition is constant, a variable is 102 * used instead of "false". A unique name for every catch-statement is 103 * necessary, which is achieved by macro EMBB_CATCH_VAR and helper macros. To 104 * avoid the unused variable warning, in addition the EMBB_UNUSED macro is 105 * used. 106 */ 107 #define EMBB_CATCH(Statement) \ 108 int EMBB_CATCH_VAR = false; \ 109 EMBB_UNUSED(EMBB_CATCH_VAR); \ 110 if (EMBB_CATCH_VAR) 111 112 /** 113 * Replaces a throw by an error message and program exit. 114 */ 115 #define EMBB_THROW(Type, Message) \ 116 { \ 117 Type e(Message); \ 118 fprintf(stderr, \ 119 "Exit program due to (not thrown) " #Type ": %s\n", e.what()); \ 120 exit(e.Code()); \ 121 } 122 #endif /* else EMBB_USE_EXCEPTIONS */ 123 124 namespace embb { 125 namespace base { 126 127 /** 128 * Abstract base class for exceptions. 129 * 130 * \ingroup CPP_BASE_EXCEPTIONS 131 */ 132 class Exception : public std::exception { 133 public: 134 /** 135 * Constructs an exception with a custom message. 136 */ Exception(const char * message)137 explicit Exception( 138 const char* message 139 /**< [IN] Error message */ 140 ) : message_(message) {} 141 142 /** 143 * Destructs the exception. 144 */ ~Exception()145 virtual ~Exception() throw() {} 146 147 /** 148 * Constructs an exception by copying from an existing one. 149 */ Exception(const Exception & e)150 Exception( 151 const Exception& e 152 /**< [IN] %Exception to be copied */ 153 ) : message_(e.message_) {} 154 155 /** 156 * Assigns an existing exception. 157 * 158 * \return Reference to \c *this 159 */ 160 Exception& operator=( 161 const Exception& e 162 /**< [IN] %Exception to assign */ 163 ) { 164 message_ = e.message_; 165 return *this; 166 } 167 168 /** 169 * Returns the error message. 170 * 171 * \return Pointer to error message 172 */ What()173 virtual const char* What() const throw() { 174 return message_; 175 } 176 177 /** 178 * Returns an integer code representing the exception. 179 * 180 * \return %Exception code 181 */ 182 virtual int Code() const = 0; 183 184 private: 185 /** 186 * Holds error message 187 */ 188 const char* message_; 189 }; 190 191 /** 192 * Indicates lack of memory necessary to allocate a resource. 193 * 194 * \ingroup CPP_BASE_EXCEPTIONS 195 */ 196 class NoMemoryException : public Exception { 197 public: 198 /** 199 * Constructs an exception with the specified message 200 */ NoMemoryException(const char * message)201 explicit NoMemoryException( 202 const char* message 203 /**< [IN] Error message */ 204 ) : Exception(message) {} Code()205 virtual int Code() const { return EMBB_NOMEM; } 206 }; 207 208 /** 209 * Indicates business (unavailability) of a required resource. 210 * 211 * \ingroup CPP_BASE_EXCEPTIONS 212 */ 213 class ResourceBusyException : public Exception { 214 public: 215 /** 216 * Constructs an exception with the specified message 217 */ ResourceBusyException(const char * message)218 explicit ResourceBusyException( 219 const char* message 220 /**< [IN] Error message */ 221 ) : Exception(message) {} Code()222 virtual int Code() const { return EMBB_BUSY; } 223 }; 224 225 /** 226 * Indicates a numeric underflow. 227 * 228 * \ingroup CPP_BASE_EXCEPTIONS 229 */ 230 class UnderflowException : public Exception { 231 public: 232 /** 233 * Constructs an exception with the specified message 234 */ UnderflowException(const char * message)235 explicit UnderflowException( 236 const char* message 237 /**< [IN] Error message */ 238 ) : Exception(message) {} Code()239 virtual int Code() const { return EMBB_UNDERFLOW; } 240 }; 241 242 /** 243 * Indicates a numeric overflow. 244 * 245 * \ingroup CPP_BASE_EXCEPTIONS 246 */ 247 class OverflowException : public Exception { 248 public: 249 /** 250 * Constructs an exception with the specified message 251 */ OverflowException(const char * message)252 explicit OverflowException( 253 const char* message 254 /**< [IN] Error message */ 255 ) : Exception(message) {} Code()256 virtual int Code() const { return EMBB_OVERFLOW; } 257 }; 258 259 /** 260 * Indicates a general error. 261 * 262 * \ingroup CPP_BASE_EXCEPTIONS 263 */ 264 class ErrorException : public Exception { 265 public: 266 /** 267 * Constructs an exception with the specified message 268 */ ErrorException(const char * message)269 explicit ErrorException( 270 const char* message 271 /**< [IN] Error message */ 272 ) : Exception(message) {} Code()273 virtual int Code() const { return EMBB_ERROR; } 274 }; 275 276 } // namespace base 277 } // namespace embb 278 279 #endif // EMBB_BASE_EXCEPTIONS_H_ 280