Merge changes from the Witness.

This commit is contained in:
castano@gmail.com
2013-06-07 17:53:55 +00:00
parent 634229a842
commit 94d0635285
49 changed files with 1974 additions and 625 deletions

View File

@ -108,7 +108,7 @@ namespace nv
void push_back( const T & val );
void pushBack( const T & val );
void append( const T & val );
Array<T> & append( const T & val );
Array<T> & operator<< ( T & t );
void pop_back();
void popBack();
@ -160,7 +160,7 @@ namespace nv
friend void swap(Array<Typ> & a, Array<Typ> & b);
protected:
protected:
void setArraySize(uint new_size);
void setArrayCapacity(uint new_capacity);

View File

@ -22,7 +22,7 @@ namespace nv
NV_FORCEINLINE void Array<T>::push_back( const T & val )
{
#if 1
nvDebugCheck(&val < m_buffer || &val > m_buffer+m_size);
nvDebugCheck(&val < m_buffer || &val >= m_buffer+m_size);
uint old_size = m_size;
uint new_size = m_size + 1;
@ -57,9 +57,10 @@ namespace nv
push_back(val);
}
template <typename T>
NV_FORCEINLINE void Array<T>::append( const T & val )
NV_FORCEINLINE Array<T> & Array<T>::append( const T & val )
{
push_back(val);
return *this;
}
// Qt like push operator.

View File

@ -66,7 +66,7 @@
# endif
#endif
#define USE_SEPARATE_THREAD 1
#define NV_USE_SEPARATE_THREAD 1
using namespace nv;
@ -101,7 +101,7 @@ namespace
// We should try to simplify the top level filter as much as possible.
// http://www.nynaeve.net/?p=128
#if USE_SEPARATE_THREAD
#if NV_USE_SEPARATE_THREAD
// The critical section enforcing the requirement that only one exception be
// handled by a handler at a time.
@ -121,7 +121,7 @@ namespace
static DWORD s_requesting_thread_id = 0;
static EXCEPTION_POINTERS * s_exception_info = NULL;
#endif // USE_SEPARATE_THREAD
#endif // NV_USE_SEPARATE_THREAD
struct MinidumpCallbackContext {
@ -236,7 +236,7 @@ namespace
return true;
}
#if USE_SEPARATE_THREAD
#if NV_USE_SEPARATE_THREAD
static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter) {
nvDebugCheck(s_handler_start_semaphore != NULL);
@ -256,7 +256,7 @@ namespace
return 0;
}
#endif // USE_SEPARATE_THREAD
#endif // NV_USE_SEPARATE_THREAD
static bool hasStackTrace() {
return true;
@ -387,7 +387,9 @@ namespace
DWORD dwDisplacement;
if (!SymGetLineFromAddr64(hProcess, ip, &dwDisplacement, &theLine))
{
builder.format("unknown(%08X) : %s\n", (uint32)ip, pFunc);
// Do not print unknown symbols anymore.
break;
//builder.format("unknown(%08X) : %s\n", (uint32)ip, pFunc);
}
else
{
@ -404,6 +406,10 @@ namespace
}
lines.append(builder.release());
if (pFunc != NULL && strcmp(pFunc, "WinMain") == 0) {
break;
}
}
}
}
@ -413,7 +419,7 @@ namespace
static LONG WINAPI handleException(EXCEPTION_POINTERS * pExceptionInfo)
{
EnterCriticalSection(&s_handler_critical_section);
#if USE_SEPARATE_THREAD
#if NV_USE_SEPARATE_THREAD
s_requesting_thread_id = GetCurrentThreadId();
s_exception_info = pExceptionInfo;
@ -474,6 +480,36 @@ namespace
}
static void handleInvalidParameter(const wchar_t * expresion, const wchar_t * function, const wchar_t * file, unsigned int line, uintptr_t reserved) {
size_t convertedCharCount = 0;
StringBuilder tmp;
if (expresion != NULL) {
uint size = toU32(wcslen(expresion) + 1);
tmp.reserve(size);
wcstombs_s(&convertedCharCount, tmp.str(), size, expresion, _TRUNCATE);
nvDebug("*** Invalid parameter: %s\n", tmp.str());
if (file != NULL) {
size = toU32(wcslen(file) + 1);
tmp.reserve(size);
wcstombs_s(&convertedCharCount, tmp.str(), size, file, _TRUNCATE);
nvDebug(" On file: %s\n", tmp.str());
if (function != NULL) {
size = toU32(wcslen(function) + 1);
tmp.reserve(size);
wcstombs_s(&convertedCharCount, tmp.str(), size, function, _TRUNCATE);
nvDebug(" On function: %s\n", tmp.str());
}
nvDebug(" On line: %u\n", line);
}
}
nvDebugBreak();
TerminateProcess(GetCurrentProcess(), EXIT_FAILURE + 8);
}
@ -706,16 +742,22 @@ namespace
}
// Assert handler method.
virtual int assertion( const char * exp, const char * file, int line, const char * func/*=NULL*/ )
virtual int assertion(const char * exp, const char * file, int line, const char * func, const char * msg, va_list arg)
{
int ret = NV_ABORT_EXIT;
StringBuilder error_string;
if( func != NULL ) {
error_string.format( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line );
error_string.format("*** Assertion failed: %s\n On file: %s\n On line: %d\n", exp, file, line );
if (func != NULL) {
error_string.appendFormat(" On function: %s\n", func);
}
else {
error_string.format( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line );
if (msg != NULL) {
error_string.append(" Message: ");
va_list tmp;
va_copy(tmp, arg);
error_string.appendFormatList(msg, tmp);
va_end(tmp);
error_string.append("\n");
}
nvDebug( error_string.str() );
@ -760,7 +802,7 @@ namespace
struct Xbox360AssertHandler : public AssertHandler
{
// Assert handler method.
virtual int assertion( const char * exp, const char * file, int line, const char * func/*=NULL*/ )
virtual int assertion(const char * exp, const char * file, int line, const char * func, const char * msg, va_list arg)
{
int ret = NV_ABORT_EXIT;
@ -786,14 +828,47 @@ namespace
return ret;
}
};
#elif NV_OS_ORBIS
/** Orbis assert handler. */
struct OrbisAssertHandler : public AssertHandler
{
// Assert handler method.
virtual int assertion(const char * exp, const char * file, int line, const char * func, const char * msg, va_list arg)
{
if( func != NULL ) {
nvDebug( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line );
}
else {
nvDebug( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line );
}
//SBtodoORBIS print stack trace
/*if (hasStackTrace())
{
void * trace[64];
int size = backtrace(trace, 64);
printStackTrace(trace, size, 2);
}*/
//SBtodoORBIS check for debugger present
//if (debug::isDebuggerPresent())
nvDebugBreak();
return NV_ABORT_DEBUG;
}
};
#else
/** Unix assert handler. */
struct UnixAssertHandler : public AssertHandler
{
// Assert handler method.
virtual int assertion(const char * exp, const char * file, int line, const char * func)
virtual int assertion(const char * exp, const char * file, int line, const char * func, const char * msg, va_list arg)
{
int ret = NV_ABORT_EXIT;
if( func != NULL ) {
nvDebug( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line );
}
@ -816,9 +891,13 @@ namespace
}
#endif
if( ret == NV_ABORT_EXIT ) {
// Exit cleanly.
exit(EXIT_FAILURE + 1);
}
return ret;
}
};
#endif
@ -827,22 +906,27 @@ namespace
/// Handle assertion through the assert handler.
int nvAbort(const char * exp, const char * file, int line, const char * func/*=NULL*/)
int nvAbort(const char * exp, const char * file, int line, const char * func/*=NULL*/, const char * msg/*= NULL*/, ...)
{
#if NV_OS_WIN32 //&& NV_CC_MSVC
static Win32AssertHandler s_default_assert_handler;
#elif NV_OS_XBOX
static Xbox360AssertHandler s_default_assert_handler;
#elif NV_OS_ORBIS
static OrbisAssertHandler s_default_assert_handler;
#else
static UnixAssertHandler s_default_assert_handler;
#endif
if (s_assert_handler != NULL) {
return s_assert_handler->assertion( exp, file, line, func );
}
else {
return s_default_assert_handler.assertion( exp, file, line, func );
}
va_list arg;
va_start(arg,msg);
AssertHandler * handler = s_assert_handler != NULL ? s_assert_handler : &s_default_assert_handler;
int result = handler->assertion(exp, file, line, func, msg, arg);
va_end(arg);
return result;
}
// Abnormal termination. Create mini dump and output call stack.
@ -914,6 +998,26 @@ void debug::dumpInfo()
#endif
}
/// Dump callstack using the specified handler.
void debug::dumpCallstack(MessageHandler *messageHandler, int callstackLevelsToSkip /*= 0*/)
{
#if (NV_OS_WIN32 && NV_CC_MSVC) || (defined(HAVE_SIGNAL_H) && defined(HAVE_EXECINFO_H))
if (hasStackTrace())
{
void * trace[64];
int size = backtrace(trace, 64);
Array<const char *> lines;
writeStackTrace(trace, size, callstackLevelsToSkip + 1, lines); // + 1 to skip the call to dumpCallstack
for (uint i = 0; i < lines.count(); i++) {
messageHandler->log(lines[i], NULL);
delete lines[i];
}
}
#endif
}
/// Set the debug message handler.
void debug::setMessageHandler(MessageHandler * message_handler)
@ -939,9 +1043,8 @@ void debug::resetAssertHandler()
s_assert_handler = NULL;
}
#if NV_OS_WIN32
#if USE_SEPARATE_THREAD
#if NV_USE_SEPARATE_THREAD
static void initHandlerThread()
{
@ -984,7 +1087,7 @@ static void shutHandlerThread() {
// @@ Free stuff. Terminate thread.
}
#endif // USE_SEPARATE_THREAD
#endif // NV_USE_SEPARATE_THREAD
#endif // NV_OS_WIN32
@ -1009,7 +1112,7 @@ void debug::enableSigHandler(bool interactive)
}
#if USE_SEPARATE_THREAD
#if NV_USE_SEPARATE_THREAD
initHandlerThread();
#endif

View File

@ -70,11 +70,12 @@
} \
NV_MULTI_LINE_MACRO_END
#define nvAssertMacroWithIgnoreAll(exp) \
// GCC, LLVM need "##" before the __VA_ARGS__, MSVC doesn't care
#define nvAssertMacroWithIgnoreAll(exp,...) \
NV_MULTI_LINE_MACRO_BEGIN \
static bool ignoreAll = false; \
if (!ignoreAll && !(exp)) { \
int result = nvAbort(#exp, __FILE__, __LINE__, __FUNC__); \
int result = nvAbort(#exp, __FILE__, __LINE__, __FUNC__, ##__VA_ARGS__); \
if (result == NV_ABORT_DEBUG) { \
nvDebugBreak(); \
} else if (result == NV_ABORT_IGNORE) { \
@ -157,7 +158,7 @@
#endif
NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = NULL);
NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = NULL, const char * msg = NULL, ...);
NVCORE_API void NV_CDECL nvDebugPrint( const char *msg, ... ) __attribute__((format (printf, 1, 2)));
namespace nv
@ -184,7 +185,7 @@ namespace nv
// Assert handler interface.
struct AssertHandler {
virtual int assertion(const char *exp, const char *file, int line, const char *func = NULL) = 0;
virtual int assertion(const char *exp, const char *file, int line, const char *func, const char *msg, va_list arg) = 0;
virtual ~AssertHandler() {}
};
@ -192,6 +193,7 @@ namespace nv
namespace debug
{
NVCORE_API void dumpInfo();
NVCORE_API void dumpCallstack( MessageHandler *messageHandler, int callstackLevelsToSkip = 0 );
NVCORE_API void setMessageHandler( MessageHandler * messageHandler );
NVCORE_API void resetMessageHandler();

View File

@ -27,6 +27,7 @@
#define NV_FASTCALL __attribute__((fastcall))
#define NV_FORCEINLINE __attribute__((always_inline)) inline
#define NV_DEPRECATED __attribute__((deprecated))
#define NV_THREAD_LOCAL //ACS: there's no "__thread" or equivalent on iOS/OSX
#if __GNUC__ > 2
#define NV_PURE __attribute__((pure))
@ -38,6 +39,8 @@
#define NV_NOINLINE __attribute__((noinline))
// Define __FUNC__ properly.
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2

View File

@ -25,8 +25,9 @@
#endif
#define NV_FASTCALL __attribute__((fastcall))
#define NV_FORCEINLINE inline __attribute__((always_inline))
#define NV_FORCEINLINE __attribute__((always_inline))
#define NV_DEPRECATED __attribute__((deprecated))
#define NV_THREAD_LOCAL __thread
#if __GNUC__ > 2

View File

@ -103,10 +103,25 @@ namespace nv
clearerr(m_fp);
}
// @@ The original implementation uses feof, which only returns true when we attempt to read *past* the end of the stream.
// That is, if we read the last byte of a file, then isAtEnd would still return false, even though the stream pointer is at the file end. This is not the intent and was inconsistent with the implementation of the MemoryStream, a better
// implementation uses use ftell and fseek to determine our location within the file.
virtual bool isAtEnd() const
{
nvDebugCheck(m_fp != NULL);
return feof( m_fp ) != 0;
//return feof( m_fp ) != 0;
#if NV_OS_WIN32
uint pos = _ftell_nolock(m_fp);
_fseek_nolock(m_fp, 0, SEEK_END);
uint end = _ftell_nolock(m_fp);
_fseek_nolock(m_fp, pos, SEEK_SET);
#else
uint pos = (uint)ftell(m_fp);
fseek(m_fp, 0, SEEK_END);
uint end = (uint)ftell(m_fp);
fseek(m_fp, pos, SEEK_SET);
#endif
return pos == end;
}
/// Always true.

View File

@ -101,6 +101,13 @@ bool nv::strEqual(const char * s1, const char * s2)
return strCmp(s1, s2) == 0;
}
bool nv::strCaseEqual(const char * s1, const char * s2)
{
if (s1 == s2) return true;
if (s1 == NULL || s2 == NULL) return false;
return strCaseCmp(s1, s2) == 0;
}
bool nv::strBeginsWith(const char * str, const char * prefix)
{
//return strstr(str, prefix) == dst;
@ -326,7 +333,7 @@ StringBuilder & StringBuilder::append( const char * s )
if (m_str == NULL) {
m_size = slen + 1;
m_str = strAlloc(m_size);
memcpy(m_str, s, m_size + 1);
memcpy(m_str, s, m_size);
}
else {
const uint len = uint(strlen( m_str ));

View File

@ -35,12 +35,12 @@ namespace nv
uint operator()(const char * str) const { return strHash(str); }
};
NVCORE_API uint strLen(const char * str) NV_PURE;
NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API bool strEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
NVCORE_API bool strCaseEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
template <> struct Equal<const char *> {
bool operator()(const char * a, const char * b) const { return strEqual(a, b); }

View File

@ -23,7 +23,7 @@
#define NV_INT32_MAX 2147483647
#define NV_UINT32_MAX 0xffffffff
#define NV_INT64_MAX POSH_I64(9223372036854775807)
#define NV_INT64_MIN (-POSH_I64(9223372036854775808))
#define NV_INT64_MIN (-POSH_I64(9223372036854775807)-1)
#define NV_UINT64_MAX POSH_U64(0xffffffffffffffff)
#define NV_HALF_MAX 65504.0F

View File

@ -31,12 +31,16 @@
// NV_OS_UNIX
// NV_OS_DARWIN
// NV_OS_XBOX
// NV_OS_ORBIS
// NV_OS_IOS
#define NV_OS_STRING POSH_OS_STRING
#if defined POSH_OS_LINUX
# define NV_OS_LINUX 1
# define NV_OS_UNIX 1
#elif defined POSH_OS_ORBIS
# define NV_OS_ORBIS 1
#elif defined POSH_OS_FREEBSD
# define NV_OS_FREEBSD 1
# define NV_OS_UNIX 1
@ -51,6 +55,10 @@
#elif defined POSH_OS_OSX
# define NV_OS_DARWIN 1
# define NV_OS_UNIX 1
#elif defined POSH_OS_IOS
# define NV_OS_DARWIN 1 //ACS should we keep this on IOS?
# define NV_OS_UNIX 1
# define NV_OS_IOS 1
#elif defined POSH_OS_UNIX
# define NV_OS_UNIX 1
#elif defined POSH_OS_WIN32
@ -63,6 +71,22 @@
# error "Unsupported OS"
#endif
// Threading:
// some platforms don't implement __thread or similar for thread-local-storage
#if NV_OS_UNIX || NV_OS_ORBIS || NV_OS_IOS //ACStodoIOS darwin instead of ios?
# define NV_OS_USE_PTHREAD 1
# if NV_OS_DARWIN || NV_OS_IOS
# define NV_OS_HAS_TLS_QUALIFIER 0
# else
# define NV_OS_HAS_TLS_QUALIFIER 1
# endif
#else
# define NV_OS_USE_PTHREAD 0
# define NV_OS_HAS_TLS_QUALIFIER 1
#endif
// CPUs:
// NV_CPU_X86
// NV_CPU_X86_64
@ -182,7 +206,7 @@ typedef uint32 uint;
#endif
#if __cplusplus > 199711L
#define nvStaticCheck(x) static_assert(x)
#define nvStaticCheck(x) static_assert(x, "Static assert "#x" failed")
#else
#define nvStaticCheck(x) typedef char NV_STRING_JOIN2(__static_assert_,__LINE__)[(x)]
#endif