From c78a8595fbb4c94855ca0a2c5ed93b1c25bf5cce Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 01:33:05 +0000 Subject: [PATCH 01/10] Initial work on new assert macro. --- library/PolyVoxCore/CMakeLists.txt | 2 + .../include/PolyVoxCore/Impl/ErrorHandling.h | 77 +++++++++++++++++++ .../polyvoxcore/source/Impl/ErrorHandling.cpp | 70 +++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h create mode 100644 library/polyvoxcore/source/Impl/ErrorHandling.cpp diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 614e05d7..201d8ab5 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -94,6 +94,7 @@ SET(CORE_INC_FILES ) SET(IMPL_SRC_FILES + source/Impl/ErrorHandling.cpp source/Impl/MarchingCubesTables.cpp source/Impl/RandomUnitVectors.cpp source/Impl/RandomVectors.cpp @@ -106,6 +107,7 @@ SET(IMPL_INC_FILES include/PolyVoxCore/Impl/AStarPathfinderImpl.h include/PolyVoxCore/Impl/Block.h include/PolyVoxCore/Impl/Block.inl + include/PolyVoxCore/Impl/ErrorHandling.h include/PolyVoxCore/Impl/MarchingCubesTables.h include/PolyVoxCore/Impl/RandomUnitVectors.h include/PolyVoxCore/Impl/RandomVectors.h diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h new file mode 100644 index 00000000..c3f832a3 --- /dev/null +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -0,0 +1,77 @@ +/******************************************************************************* +Copyright (c) 2005-2009 David Williams + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*******************************************************************************/ + +#ifndef __PolyVox_ErrorHandling_H__ +#define __PolyVox_ErrorHandling_H__ + +#define POLYVOX_ASSERTS_ENABLED + +namespace PolyVox +{ + namespace Assert + { + enum FailBehavior + { + Halt, + Continue, + }; + + typedef FailBehavior (*Handler)(const char* condition, const char* msg, const char* file, int line); + + Handler GetHandler(); + void SetHandler(Handler newHandler); + + FailBehavior ReportFailure(const char* condition, + const char* file, + int line, + const char* msg, ...); + } +} + +#define POLYVOX_HALT() __debugbreak() +#define POLYVOX_UNUSED(x) do { (void)sizeof(x); } while(0) + +#ifdef POLYVOX_ASSERTS_ENABLED + + #define POLYVOX_ASSERT(cond, msg, ...) \ + do \ + { \ + if (!(cond)) \ + { \ + if (PolyVox::Assert::ReportFailure(#cond, __FILE__, __LINE__, (msg), __VA_ARGS__) == \ + PolyVox::Assert::Halt) \ + POLYVOX_HALT(); \ + } \ + } while(0) + +#else + + #define POLYVOX_ASSERT(condition, msg, ...) \ + do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(msg); } while(0) + +#endif + +#define POLYVOX_STATIC_ASSERT(x) \ + typedef char polyvoxStaticAssert[(x) ? 1 : -1]; + +#endif //__PolyVox_ErrorHandling_H__ diff --git a/library/polyvoxcore/source/Impl/ErrorHandling.cpp b/library/polyvoxcore/source/Impl/ErrorHandling.cpp new file mode 100644 index 00000000..40225a44 --- /dev/null +++ b/library/polyvoxcore/source/Impl/ErrorHandling.cpp @@ -0,0 +1,70 @@ +#include "PolyVoxCore/Impl/ErrorHandling.h" + +#include +#include + +namespace PolyVox +{ + +namespace +{ + +Assert::FailBehavior DefaultHandler(const char* condition, + const char* msg, + const char* file, + const int line) +{ + std::printf("%s(%d): Assert Failure: ", file, line); + + if (condition != NULL) + std::printf("'%s' ", condition); + + if (msg != NULL) + std::printf("%s", msg); + + std::printf("\n"); + + return Assert::Halt; +} + +Assert::Handler& GetAssertHandlerInstance() +{ + static Assert::Handler s_handler = &DefaultHandler; + return s_handler; +} + +} + +Assert::Handler Assert::GetHandler() +{ + return GetAssertHandlerInstance(); +} + +void Assert::SetHandler(Assert::Handler newHandler) +{ + GetAssertHandlerInstance() = newHandler; +} + +Assert::FailBehavior Assert::ReportFailure(const char* condition, + const char* file, + const int line, + const char* msg, ...) +{ + const char* message = NULL; + if (msg != NULL) + { + char messageBuffer[1024]; + { + va_list args; + va_start(args, msg); + vsnprintf(messageBuffer, 1024, msg, args); + va_end(args); + } + + message = messageBuffer; + } + + return GetAssertHandlerInstance()(condition, message, file, line); +} + +} \ No newline at end of file From c74c1a2b4456c30e2d4ea9187114522e99f13770 Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 02:03:32 +0000 Subject: [PATCH 02/10] Work on new assert macro. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 12 +- .../polyvoxcore/source/Impl/ErrorHandling.cpp | 114 +++++++++--------- 2 files changed, 66 insertions(+), 60 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index c3f832a3..f83975e1 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -26,6 +26,13 @@ freely, subject to the following restrictions: #define POLYVOX_ASSERTS_ENABLED +/* + * Assertions + * ---------- + * The code below implements a custom assert function called POLYVOX_ASSERT which has a number of advantages compared to + * the standard C/C++ assert(). It is based on http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ which + * provides code under the MIT license. + */ namespace PolyVox { namespace Assert @@ -41,10 +48,7 @@ namespace PolyVox Handler GetHandler(); void SetHandler(Handler newHandler); - FailBehavior ReportFailure(const char* condition, - const char* file, - int line, - const char* msg, ...); + FailBehavior ReportFailure(const char* condition, const char* file, int line, const char* msg, ...); } } diff --git a/library/polyvoxcore/source/Impl/ErrorHandling.cpp b/library/polyvoxcore/source/Impl/ErrorHandling.cpp index 40225a44..8e62e9b9 100644 --- a/library/polyvoxcore/source/Impl/ErrorHandling.cpp +++ b/library/polyvoxcore/source/Impl/ErrorHandling.cpp @@ -3,68 +3,70 @@ #include #include +/* + * Assertions + * ---------- + * The code below implements a custom assert function called POLYVOX_ASSERT which has a number of advantages compared to + * the standard C/C++ assert(). It is based on http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ which + * provides code under the MIT license. + */ namespace PolyVox { - -namespace -{ - -Assert::FailBehavior DefaultHandler(const char* condition, - const char* msg, - const char* file, - const int line) -{ - std::printf("%s(%d): Assert Failure: ", file, line); - - if (condition != NULL) - std::printf("'%s' ", condition); - - if (msg != NULL) - std::printf("%s", msg); - - std::printf("\n"); - - return Assert::Halt; -} - -Assert::Handler& GetAssertHandlerInstance() -{ - static Assert::Handler s_handler = &DefaultHandler; - return s_handler; -} - -} - -Assert::Handler Assert::GetHandler() -{ - return GetAssertHandlerInstance(); -} - -void Assert::SetHandler(Assert::Handler newHandler) -{ - GetAssertHandlerInstance() = newHandler; -} - -Assert::FailBehavior Assert::ReportFailure(const char* condition, - const char* file, - const int line, - const char* msg, ...) -{ - const char* message = NULL; - if (msg != NULL) + namespace { - char messageBuffer[1024]; + Assert::FailBehavior DefaultHandler(const char* condition, const char* msg, const char* file, const int line) { - va_list args; - va_start(args, msg); - vsnprintf(messageBuffer, 1024, msg, args); - va_end(args); + std::printf("%s(%d): Assert Failure: ", file, line); + + if (condition != NULL) + std::printf("'%s' ", condition); + + if (msg != NULL) + std::printf("%s", msg); + + std::printf("\n"); + + return Assert::Halt; + } + + Assert::Handler& GetAssertHandlerInstance() + { + static Assert::Handler s_handler = &DefaultHandler; + return s_handler; } - message = messageBuffer; } - return GetAssertHandlerInstance()(condition, message, file, line); -} + Assert::Handler Assert::GetHandler() + { + return GetAssertHandlerInstance(); + } -} \ No newline at end of file + void Assert::SetHandler(Assert::Handler newHandler) + { + GetAssertHandlerInstance() = newHandler; + } + + Assert::FailBehavior Assert::ReportFailure(const char* condition, const char* file, const int line, const char* msg, ...) + { + const char* message = NULL; + if (msg != NULL) + { + char messageBuffer[1024]; + { + va_list args; + va_start(args, msg); +#if defined (_MSC_VER) + vsnprintf_s(messageBuffer, 1024, msg, args); +#else + vsnprintf(messageBuffer, 1024, msg, args); +#endif + va_end(args); + } + + message = messageBuffer; + } + + return GetAssertHandlerInstance()(condition, message, file, line); + } +} From e17271a2c72427d1c936dd4823f2572d9bdc41f4 Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 10:34:09 +0000 Subject: [PATCH 03/10] Work on new asserts. --- library/PolyVoxCore/CMakeLists.txt | 1 - .../include/PolyVoxCore/Impl/ErrorHandling.h | 57 ++++++--------- .../polyvoxcore/source/Impl/ErrorHandling.cpp | 72 ------------------- 3 files changed, 21 insertions(+), 109 deletions(-) delete mode 100644 library/polyvoxcore/source/Impl/ErrorHandling.cpp diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 201d8ab5..db97c3f3 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -94,7 +94,6 @@ SET(CORE_INC_FILES ) SET(IMPL_SRC_FILES - source/Impl/ErrorHandling.cpp source/Impl/MarchingCubesTables.cpp source/Impl/RandomUnitVectors.cpp source/Impl/RandomVectors.cpp diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index f83975e1..b99f0278 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -24,58 +24,43 @@ freely, subject to the following restrictions: #ifndef __PolyVox_ErrorHandling_H__ #define __PolyVox_ErrorHandling_H__ +#include + #define POLYVOX_ASSERTS_ENABLED -/* - * Assertions - * ---------- - * The code below implements a custom assert function called POLYVOX_ASSERT which has a number of advantages compared to - * the standard C/C++ assert(). It is based on http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ which - * provides code under the MIT license. - */ -namespace PolyVox -{ - namespace Assert - { - enum FailBehavior - { - Halt, - Continue, - }; - - typedef FailBehavior (*Handler)(const char* condition, const char* msg, const char* file, int line); - - Handler GetHandler(); - void SetHandler(Handler newHandler); - - FailBehavior ReportFailure(const char* condition, const char* file, int line, const char* msg, ...); - } -} - #define POLYVOX_HALT() __debugbreak() #define POLYVOX_UNUSED(x) do { (void)sizeof(x); } while(0) +/* + * Assertions + * ---------- + * The code below implements a custom assert function called POLYVOX_ASSERT which has a number of advantages compared + * to the standard C/C++ assert(). It is inspired by http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ + * which provides code under the MIT license. + */ + #ifdef POLYVOX_ASSERTS_ENABLED - #define POLYVOX_ASSERT(cond, msg, ...) \ + #define POLYVOX_ASSERT(condition, message) \ do \ { \ - if (!(cond)) \ + if (!(condition)) \ { \ - if (PolyVox::Assert::ReportFailure(#cond, __FILE__, __LINE__, (msg), __VA_ARGS__) == \ - PolyVox::Assert::Halt) \ - POLYVOX_HALT(); \ + std::cerr << std::endl << std::endl; \ + std::cerr << " PolyVox Assertion Failed!" << std::endl; \ + std::cerr << " -------------------------" << std::endl; \ + std::cerr << " Condition: " << #condition << std::endl; \ + std::cerr << " Message: " << (message) << std::endl; \ + std::cerr << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ + POLYVOX_HALT(); \ } \ } while(0) #else - #define POLYVOX_ASSERT(condition, msg, ...) \ - do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(msg); } while(0) + #define POLYVOX_ASSERT(condition, message) \ + do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(message); } while(0) #endif -#define POLYVOX_STATIC_ASSERT(x) \ - typedef char polyvoxStaticAssert[(x) ? 1 : -1]; - #endif //__PolyVox_ErrorHandling_H__ diff --git a/library/polyvoxcore/source/Impl/ErrorHandling.cpp b/library/polyvoxcore/source/Impl/ErrorHandling.cpp deleted file mode 100644 index 8e62e9b9..00000000 --- a/library/polyvoxcore/source/Impl/ErrorHandling.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "PolyVoxCore/Impl/ErrorHandling.h" - -#include -#include - -/* - * Assertions - * ---------- - * The code below implements a custom assert function called POLYVOX_ASSERT which has a number of advantages compared to - * the standard C/C++ assert(). It is based on http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ which - * provides code under the MIT license. - */ -namespace PolyVox -{ - namespace - { - Assert::FailBehavior DefaultHandler(const char* condition, const char* msg, const char* file, const int line) - { - std::printf("%s(%d): Assert Failure: ", file, line); - - if (condition != NULL) - std::printf("'%s' ", condition); - - if (msg != NULL) - std::printf("%s", msg); - - std::printf("\n"); - - return Assert::Halt; - } - - Assert::Handler& GetAssertHandlerInstance() - { - static Assert::Handler s_handler = &DefaultHandler; - return s_handler; - } - - } - - Assert::Handler Assert::GetHandler() - { - return GetAssertHandlerInstance(); - } - - void Assert::SetHandler(Assert::Handler newHandler) - { - GetAssertHandlerInstance() = newHandler; - } - - Assert::FailBehavior Assert::ReportFailure(const char* condition, const char* file, const int line, const char* msg, ...) - { - const char* message = NULL; - if (msg != NULL) - { - char messageBuffer[1024]; - { - va_list args; - va_start(args, msg); -#if defined (_MSC_VER) - vsnprintf_s(messageBuffer, 1024, msg, args); -#else - vsnprintf(messageBuffer, 1024, msg, args); -#endif - va_end(args); - } - - message = messageBuffer; - } - - return GetAssertHandlerInstance()(condition, message, file, line); - } -} From a3cb8f7a766dc637c71cf5316a9d6fa3082396ce Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 15:02:03 +0000 Subject: [PATCH 04/10] Now using new assert in Vector. --- library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl | 2 ++ library/PolyVoxCore/include/PolyVoxCore/Vector.h | 2 +- library/PolyVoxCore/include/PolyVoxCore/Vector.inl | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl b/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl index 45d24ada..1b9f2bd0 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl @@ -21,6 +21,8 @@ freely, subject to the following restrictions: distribution. *******************************************************************************/ +#include + namespace PolyVox { template diff --git a/library/PolyVoxCore/include/PolyVoxCore/Vector.h b/library/PolyVoxCore/include/PolyVoxCore/Vector.h index 12c3c201..db3da0f8 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Vector.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Vector.h @@ -24,11 +24,11 @@ freely, subject to the following restrictions: #ifndef __PolyVox_Vector_H__ #define __PolyVox_Vector_H__ +#include "Impl/ErrorHandling.h" #include "Impl/TypeDef.h" #include "PolyVoxForwardDeclarations.h" -#include #include #include #include diff --git a/library/PolyVoxCore/include/PolyVoxCore/Vector.inl b/library/PolyVoxCore/include/PolyVoxCore/Vector.inl index 22d3009e..65b5eba7 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Vector.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Vector.inl @@ -414,7 +414,7 @@ namespace PolyVox template inline StorageType Vector::getElement(uint32_t index) const { - assert(index < Size); + POLYVOX_ASSERT(index < Size, "Attempted to access invalid vector element."); return m_tElements[index]; } @@ -465,7 +465,7 @@ namespace PolyVox template inline void Vector::setElement(uint32_t index, StorageType tValue) { - assert(index < Size); + POLYVOX_ASSERT(index < Size, "Attempted to access invalid vector element."); m_tElements[index] = tValue; } @@ -649,7 +649,7 @@ namespace PolyVox { // Standard float rules apply for divide-by-zero m_tElements[ct] /= fLength; - assert(m_tElements[ct] == m_tElements[ct]); //Will assert if NAN + POLYVOX_ASSERT(m_tElements[ct] == m_tElements[ct], "Obtained NAN during vector normalisation. Perhaps the input vector was too short?"); } } }//namespace PolyVox From 3653528ae517d4b8f875226fe2cc6bda155e66b1 Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 16:44:34 +0100 Subject: [PATCH 05/10] POLYVOX_HALT() implementation for Linux. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index b99f0278..15570bb9 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -24,11 +24,17 @@ freely, subject to the following restrictions: #ifndef __PolyVox_ErrorHandling_H__ #define __PolyVox_ErrorHandling_H__ -#include +#include //For std::exit +#include //For std::cerr #define POLYVOX_ASSERTS_ENABLED -#define POLYVOX_HALT() __debugbreak() +#if defined(_MSC_VER) + #define POLYVOX_HALT() __debugbreak() +#else + #define POLYVOX_HALT() std::exit(EXIT_FAILURE) +#endif + #define POLYVOX_UNUSED(x) do { (void)sizeof(x); } while(0) /* From 64cd6e31b067476a13e66fa1a3d08acf0b8beb21 Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 18:16:43 +0000 Subject: [PATCH 06/10] The non-C++11 implemention of POLYVOX_STATIC_ASSERT is no longer dependent on Boost. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 23 +++++++++++++++++++ .../include/PolyVoxCore/Impl/TypeDef.h | 7 ------ .../include/PolyVoxCore/Vector.inl | 22 +++++++++--------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index 15570bb9..569802c2 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -69,4 +69,27 @@ freely, subject to the following restrictions: #endif +namespace PolyVox +{ +#if defined(HAS_CXX11_STATIC_ASSERT) + //In this case we can just use static_assert +#define POLYVOX_STATIC_ASSERT static_assert +#else + // empty default template + template + struct StaticAssert {}; + + // template specialized on true + template <> + struct StaticAssert + { + // If the static assertion is failing then this function won't exist. It will then + // appear in the error message which gives a clue to the user about what is wrong. + static void ERROR_The_static_assertion_has_failed() {} + }; + + #define POLYVOX_STATIC_ASSERT(condition, message) StaticAssert<(condition)>::ERROR_The_static_assertion_has_failed(); +#endif +} + #endif //__PolyVox_ErrorHandling_H__ diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/TypeDef.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/TypeDef.h index da1fedd5..3724efe4 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/TypeDef.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/TypeDef.h @@ -98,13 +98,6 @@ freely, subject to the following restrictions: #define polyvox_constexpr #endif -#if defined(HAS_CXX11_STATIC_ASSERT) - //In this case we can just use static_assert -#else - #include - #define static_assert(condition, message) BOOST_STATIC_ASSERT(condition) -#endif - #if defined(HAS_CXX11_CSTDINT_H) #include #else diff --git a/library/PolyVoxCore/include/PolyVoxCore/Vector.inl b/library/PolyVoxCore/include/PolyVoxCore/Vector.inl index 65b5eba7..57b3e2f0 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Vector.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Vector.inl @@ -53,7 +53,7 @@ namespace PolyVox template Vector::Vector(StorageType x, StorageType y) { - static_assert(Size == 2, "This constructor should only be used for vectors with two elements."); + POLYVOX_STATIC_ASSERT(Size == 2, "This constructor should only be used for vectors with two elements."); m_tElements[0] = x; m_tElements[1] = y; @@ -68,7 +68,7 @@ namespace PolyVox template Vector::Vector(StorageType x, StorageType y, StorageType z) { - static_assert(Size == 3, "This constructor should only be used for vectors with three elements."); + POLYVOX_STATIC_ASSERT(Size == 3, "This constructor should only be used for vectors with three elements."); m_tElements[0] = x; m_tElements[1] = y; @@ -86,7 +86,7 @@ namespace PolyVox template Vector::Vector(StorageType x, StorageType y, StorageType z, StorageType w) { - static_assert(Size == 4, "This constructor should only be used for vectors with four elements."); + POLYVOX_STATIC_ASSERT(Size == 4, "This constructor should only be used for vectors with four elements."); m_tElements[0] = x; m_tElements[1] = y; @@ -129,14 +129,14 @@ namespace PolyVox template Vector::~Vector(void) { - // We put the static_asserts in the destructor because there is one one of these, + // We put the static asserts in the destructor because there is one one of these, // where as there are multiple constructors. // Force a vector to have a length greater than one. There is no need for a // vector with one element, and supporting this would cause confusion over the // behaviour of the constructor taking a single value, as this fills all elements // to that value rather than just the first one. - static_assert(Size > 1, "Vector must have a length greater than one."); + POLYVOX_STATIC_ASSERT(Size > 1, "Vector must have a length greater than one."); } /** @@ -442,7 +442,7 @@ namespace PolyVox template inline StorageType Vector::getZ(void) const { - static_assert(Size >= 3, "You can only get the 'z' component from a vector with at least three elements."); + POLYVOX_STATIC_ASSERT(Size >= 3, "You can only get the 'z' component from a vector with at least three elements."); return m_tElements[2]; } @@ -453,7 +453,7 @@ namespace PolyVox template inline StorageType Vector::getW(void) const { - static_assert(Size >= 4, "You can only get the 'w' component from a vector with at least four elements."); + POLYVOX_STATIC_ASSERT(Size >= 4, "You can only get the 'w' component from a vector with at least four elements."); return m_tElements[3]; } @@ -491,7 +491,7 @@ namespace PolyVox template inline void Vector::setElements(StorageType x, StorageType y, StorageType z) { - static_assert(Size >= 3, "You can only use this version of setElements() on a vector with at least three elements."); + POLYVOX_STATIC_ASSERT(Size >= 3, "You can only use this version of setElements() on a vector with at least three elements."); m_tElements[0] = x; m_tElements[1] = y; @@ -508,7 +508,7 @@ namespace PolyVox template inline void Vector::setElements(StorageType x, StorageType y, StorageType z, StorageType w) { - static_assert(Size >= 4, "You can only use this version of setElements() on a vector with at least four elements."); + POLYVOX_STATIC_ASSERT(Size >= 4, "You can only use this version of setElements() on a vector with at least four elements."); m_tElements[0] = x; m_tElements[1] = y; @@ -540,7 +540,7 @@ namespace PolyVox template inline void Vector::setZ(StorageType tZ) { - static_assert(Size >= 3, "You can only set the 'w' component from a vector with at least three elements."); + POLYVOX_STATIC_ASSERT(Size >= 3, "You can only set the 'w' component from a vector with at least three elements."); m_tElements[2] = tZ; } @@ -551,7 +551,7 @@ namespace PolyVox template inline void Vector::setW(StorageType tW) { - static_assert(Size >= 4, "You can only set the 'w' component from a vector with at least four elements."); + POLYVOX_STATIC_ASSERT(Size >= 4, "You can only set the 'w' component from a vector with at least four elements."); m_tElements[3] = tW; } From ecad915001c3d9731aaa868d72a39535fa98a009 Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 20:18:46 +0000 Subject: [PATCH 07/10] Tidied up some code. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index 569802c2..b4efd2f9 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -69,27 +69,27 @@ freely, subject to the following restrictions: #endif -namespace PolyVox -{ #if defined(HAS_CXX11_STATIC_ASSERT) //In this case we can just use static_assert -#define POLYVOX_STATIC_ASSERT static_assert + #define POLYVOX_STATIC_ASSERT static_assert #else - // empty default template - template - struct StaticAssert {}; - - // template specialized on true - template <> - struct StaticAssert + namespace PolyVox { - // If the static assertion is failing then this function won't exist. It will then - // appear in the error message which gives a clue to the user about what is wrong. - static void ERROR_The_static_assertion_has_failed() {} - }; + // empty default template + template + struct StaticAssert {}; + + // template specialized on true + template <> + struct StaticAssert + { + // If the static assertion is failing then this function won't exist. It will then + // appear in the error message which gives a clue to the user about what is wrong. + static void ERROR_The_static_assertion_has_failed() {} + }; + } #define POLYVOX_STATIC_ASSERT(condition, message) StaticAssert<(condition)>::ERROR_The_static_assertion_has_failed(); #endif -} #endif //__PolyVox_ErrorHandling_H__ From 9ca84dc0e15f3109069b3d9e488e4af3846d020d Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 20:24:55 +0000 Subject: [PATCH 08/10] Updated CHANGELOG.txt --- CHANGELOG.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5cceff72..b96f18ad 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,6 +2,10 @@ Changes for PolyVox version 0.3 =============================== This release has focused on... (some introduction here). +Error Handling +-------------- +PolyVox now has it's own POLYVOX_ASSERT() macro rather than using the standard assert(). This has some advantages such as allowing a message to be printed and providing file/line information, and it is also possible to enable/disable it independantly of whether you are making a debug or release build + Volume wrap modes ----------------- This release has seen a overhaul of the way PolyVox handles voxel positions which are outside of the volume. It used to be the case that you could specify a border value which would be returned whenever an out-of-volume access was performed, but this was not flexible enough for all use cases. You can now choose between different wrapping modes (border, clamp, etc) and apply them to both the volume itself or to samplers. If you have multiple samplers pointing at the same volume then you can choose to have different wrap modes for each of them. From 25a4ff1c8ed3ca7dfb73e1136bf84ece849ed4bf Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 26 Dec 2012 20:27:29 +0000 Subject: [PATCH 09/10] Added comment. --- .../PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index b4efd2f9..88415f74 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -69,6 +69,12 @@ freely, subject to the following restrictions: #endif +/* + * Static Assertions + * ----------------- + * These map to C+11 static_assert if available or our own implentation otherwise. + */ + #if defined(HAS_CXX11_STATIC_ASSERT) //In this case we can just use static_assert #define POLYVOX_STATIC_ASSERT static_assert From 4f7a6256a9fbbc17aadc5b28c3a30961f6a42b77 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sat, 29 Dec 2012 00:11:23 +0000 Subject: [PATCH 10/10] The throwing of exceptions can now be disabled, and in this case a handler function is called instead. --- library/PolyVoxCore/CMakeLists.txt | 1 + .../include/PolyVoxCore/Impl/ErrorHandling.h | 25 ++++++++++++++++++- library/PolyVoxCore/source/Impl/Utility.cpp | 12 ++++----- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 34deabef..f964a8d5 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -94,6 +94,7 @@ SET(CORE_INC_FILES ) SET(IMPL_SRC_FILES + source/Impl/ErrorHandling.cpp source/Impl/MarchingCubesTables.cpp source/Impl/RandomUnitVectors.cpp source/Impl/RandomVectors.cpp diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index 88415f74..d3ef8b49 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -26,8 +26,10 @@ freely, subject to the following restrictions: #include //For std::exit #include //For std::cerr +#include #define POLYVOX_ASSERTS_ENABLED +//#define POLYVOX_THROW_ENABLED #if defined(_MSC_VER) #define POLYVOX_HALT() __debugbreak() @@ -54,7 +56,7 @@ freely, subject to the following restrictions: { \ std::cerr << std::endl << std::endl; \ std::cerr << " PolyVox Assertion Failed!" << std::endl; \ - std::cerr << " -------------------------" << std::endl; \ + std::cerr << " =========================" << std::endl; \ std::cerr << " Condition: " << #condition << std::endl; \ std::cerr << " Message: " << (message) << std::endl; \ std::cerr << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ @@ -98,4 +100,25 @@ freely, subject to the following restrictions: #define POLYVOX_STATIC_ASSERT(condition, message) StaticAssert<(condition)>::ERROR_The_static_assertion_has_failed(); #endif +/* + * Exceptions + * ---------- + * ... + */ +#ifdef POLYVOX_THROW_ENABLED + #define POLYVOX_THROW(type, message) throw type((message)) +#else + namespace PolyVox + { + typedef void (*ThrowHandler)(std::exception& e, const char* file, int line); + + ThrowHandler getThrowHandler(); + void setThrowHandler(ThrowHandler newHandler); + } + + #define POLYVOX_THROW(type, message) \ + type except = (type)((message)); \ + getThrowHandler()((except), __FILE__, __LINE__) +#endif + #endif //__PolyVox_ErrorHandling_H__ diff --git a/library/PolyVoxCore/source/Impl/Utility.cpp b/library/PolyVoxCore/source/Impl/Utility.cpp index 6e907ab9..c82c9630 100644 --- a/library/PolyVoxCore/source/Impl/Utility.cpp +++ b/library/PolyVoxCore/source/Impl/Utility.cpp @@ -21,11 +21,9 @@ freely, subject to the following restrictions: distribution. *******************************************************************************/ +#include "PolyVoxCore/Impl/ErrorHandling.h" #include "PolyVoxCore/Impl/Utility.h" -#include -#include - namespace PolyVox { //Note: this function only works for inputs which are a power of two and not zero @@ -33,17 +31,17 @@ namespace PolyVox uint8_t logBase2(uint32_t uInput) { //Debug mode validation - assert(uInput != 0); - assert(isPowerOf2(uInput)); + POLYVOX_ASSERT(uInput != 0, "Cannot compute the log of zero."); + POLYVOX_ASSERT(isPowerOf2(uInput), "Input must be a power of two in order to compute the log."); //Release mode validation if(uInput == 0) { - throw std::invalid_argument("Cannot compute the log of zero."); + POLYVOX_THROW(std::invalid_argument, "Cannot compute the log of zero."); } if(!isPowerOf2(uInput)) { - throw std::invalid_argument("Input must be a power of two in order to compute the log."); + POLYVOX_THROW(std::invalid_argument, "Input must be a power of two in order to compute the log."); } uint32_t uResult = 0;