PolyVox  0.3.0-dev
Open source voxel management library
ErrorHandling.h
Go to the documentation of this file.
1 /*******************************************************************************
2 Copyright (c) 2005-2009 David Williams
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11 
12  1. The origin of this software must not be misrepresented; you must not
13  claim that you wrote the original software. If you use this software
14  in a product, an acknowledgment in the product documentation would be
15  appreciated but is not required.
16 
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19 
20  3. This notice may not be removed or altered from any source
21  distribution.
22 *******************************************************************************/
23 
24 #ifndef __PolyVox_ErrorHandling_H__
25 #define __PolyVox_ErrorHandling_H__
26 
28 
29 #include <cstdlib> //For std::exit
30 #include <iostream> //For std::cerr
31 #include <stdexcept>
32 
33 #if defined(_MSC_VER)
34  // In Visual Studio we can use this function to go into the debugger.
35  #define POLYVOX_HALT() __debugbreak()
36 #else
37  // On other platforms we just halt by forcing a crash.
38  // Hopefully this puts us in the debugger if one is running
39  #define POLYVOX_HALT() *((unsigned int*)0) = 0xDEAD
40 #endif
41 
42 // Macros cannot contain #ifdefs, but some of our macros need to disable warnings and such warning supression is
43 // platform specific. But macros can contain other macros, so we create macros to control the warnings and use
44 // those instead. This set of warning supression macros can be extended to GCC/Clang when required.
45 #if defined(_MSC_VER)
46  #define POLYVOX_MSC_WARNING_PUSH __pragma(warning(push))
47  #define POLYVOX_DISABLE_MSC_WARNING(x) __pragma(warning(disable:x))
48  #define POLYVOX_MSC_WARNING_POP __pragma(warning(pop))
49 #else
50  #define POLYVOX_MSC_WARNING_PUSH
51  #define POLYVOX_DISABLE_MSC_WARNING(x)
52  #define POLYVOX_MSC_WARNING_POP
53 #endif
54 
55 #define POLYVOX_UNUSED(x) do { (void)sizeof(x); } while(0)
56 
57 /*
58  * Assertions
59  * ----------
60  * The code below implements a custom assert function called POLYVOX_ASSERT which has a number of advantages compared
61  * to the standard C/C++ assert(). It is inspired by http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
62  * which provides code under the MIT license.
63  */
64 
65 #ifdef POLYVOX_ASSERTS_ENABLED
66 
67  #define POLYVOX_ASSERT(condition, message) \
68  /* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
69  but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
70  (http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
71  POLYVOX_MSC_WARNING_PUSH \
72  POLYVOX_DISABLE_MSC_WARNING(4127) \
73  do \
74  { \
75  if (!(condition)) \
76  { \
77  std::cerr << std::endl << std::endl; \
78  std::cerr << " PolyVox Assertion Failed!" << std::endl; \
79  std::cerr << " =========================" << std::endl; \
80  std::cerr << " Condition: " << #condition << std::endl; \
81  std::cerr << " Message: " << (message) << std::endl; \
82  std::cerr << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \
83  POLYVOX_HALT(); \
84  } \
85  } while(0) \
86  POLYVOX_MSC_WARNING_POP
87 
88 #else
89 
90  #define POLYVOX_ASSERT(condition, message) \
91  /* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
92  but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
93  (http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
94  POLYVOX_MSC_WARNING_PUSH \
95  POLYVOX_DISABLE_MSC_WARNING(4127) \
96  do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(message); } while(0) \
97  POLYVOX_MSC_WARNING_POP
98 
99 #endif
100 
101 /*
102  * Static Assertions
103  * -----------------
104  * These map to C+11 static_assert if available or our own implentation otherwise.
105  */
106 
107 #if defined(HAS_CXX11_STATIC_ASSERT)
108  //In this case we can just use static_assert
109  #define POLYVOX_STATIC_ASSERT static_assert
110 #else
111  namespace PolyVox
112  {
113  // empty default template
114  template <bool b>
115  struct StaticAssert {};
116 
117  // template specialized on true
118  template <>
119  struct StaticAssert<true>
120  {
121  // If the static assertion is failing then this function won't exist. It will then
122  // appear in the error message which gives a clue to the user about what is wrong.
123  static void ERROR_The_static_assertion_has_failed() {}
124  };
125  }
126 
127  #define POLYVOX_STATIC_ASSERT(condition, message) StaticAssert<(condition)>::ERROR_The_static_assertion_has_failed();
128 #endif
129 
130 /*
131  * Exceptions
132  * ----------
133  * ...
134  */
135 #ifdef POLYVOX_THROW_ENABLED
136  #define POLYVOX_THROW(type, message) throw type((message))
137 #else
138  namespace PolyVox
139  {
140  typedef void (*ThrowHandler)(std::exception& e, const char* file, int line);
141 
143  void setThrowHandler(ThrowHandler newHandler);
144  }
145 
146  #define POLYVOX_THROW(type, message) \
147  type except = (type)((message)); \
148  getThrowHandler()((except), __FILE__, __LINE__)
149 #endif
150 
151 #endif //__PolyVox_ErrorHandling_H__