summaryrefslogtreecommitdiff
path: root/thirdparty/bullet/LinearMath/btQuickprof.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/bullet/LinearMath/btQuickprof.cpp')
-rw-r--r--thirdparty/bullet/LinearMath/btQuickprof.cpp789
1 files changed, 789 insertions, 0 deletions
diff --git a/thirdparty/bullet/LinearMath/btQuickprof.cpp b/thirdparty/bullet/LinearMath/btQuickprof.cpp
new file mode 100644
index 0000000000..aed3104a6e
--- /dev/null
+++ b/thirdparty/bullet/LinearMath/btQuickprof.cpp
@@ -0,0 +1,789 @@
+/*
+
+***************************************************************************************************
+**
+** profile.cpp
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
+
+// Credits: The Clock class was inspired by the Timer classes in
+// Ogre (www.ogre3d.org).
+
+#include "btQuickprof.h"
+#include "btThreads.h"
+
+
+
+
+#ifdef __CELLOS_LV2__
+#include <sys/sys_time.h>
+#include <sys/time_util.h>
+#include <stdio.h>
+#endif
+
+#if defined (SUNOS) || defined (__SUNOS__)
+#include <stdio.h>
+#endif
+#ifdef __APPLE__
+#include <mach/mach_time.h>
+#include <TargetConditionals.h>
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+
+#define BT_USE_WINDOWS_TIMERS
+#define WIN32_LEAN_AND_MEAN
+#define NOWINRES
+#define NOMCX
+#define NOIME
+
+#ifdef _XBOX
+ #include <Xtl.h>
+#else //_XBOX
+ #include <windows.h>
+
+#if WINVER <0x0602
+#define GetTickCount64 GetTickCount
+#endif
+
+#endif //_XBOX
+
+#include <time.h>
+
+
+#else //_WIN32
+#include <sys/time.h>
+
+#ifdef BT_LINUX_REALTIME
+//required linking against rt (librt)
+#include <time.h>
+#endif //BT_LINUX_REALTIME
+
+#endif //_WIN32
+
+#define mymin(a,b) (a > b ? a : b)
+
+struct btClockData
+{
+
+#ifdef BT_USE_WINDOWS_TIMERS
+ LARGE_INTEGER mClockFrequency;
+ LONGLONG mStartTick;
+ LARGE_INTEGER mStartTime;
+#else
+#ifdef __CELLOS_LV2__
+ uint64_t mStartTime;
+#else
+#ifdef __APPLE__
+ uint64_t mStartTimeNano;
+#endif
+ struct timeval mStartTime;
+#endif
+#endif //__CELLOS_LV2__
+
+};
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+btClock::btClock()
+{
+ m_data = new btClockData;
+#ifdef BT_USE_WINDOWS_TIMERS
+ QueryPerformanceFrequency(&m_data->mClockFrequency);
+#endif
+ reset();
+}
+
+btClock::~btClock()
+{
+ delete m_data;
+}
+
+btClock::btClock(const btClock& other)
+{
+ m_data = new btClockData;
+ *m_data = *other.m_data;
+}
+
+btClock& btClock::operator=(const btClock& other)
+{
+ *m_data = *other.m_data;
+ return *this;
+}
+
+
+ /// Resets the initial reference time.
+void btClock::reset()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+ QueryPerformanceCounter(&m_data->mStartTime);
+ m_data->mStartTick = GetTickCount64();
+#else
+#ifdef __CELLOS_LV2__
+
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET( newTime );
+ m_data->mStartTime = newTime;
+#else
+#ifdef __APPLE__
+ m_data->mStartTimeNano = mach_absolute_time();
+#endif
+ gettimeofday(&m_data->mStartTime, 0);
+#endif
+#endif
+}
+
+/// Returns the time in ms since the last call to reset or since
+/// the btClock was created.
+unsigned long long int btClock::getTimeMilliseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+ LARGE_INTEGER currentTime;
+ QueryPerformanceCounter(&currentTime);
+ LONGLONG elapsedTime = currentTime.QuadPart -
+ m_data->mStartTime.QuadPart;
+ // Compute the number of millisecond ticks elapsed.
+ unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
+ m_data->mClockFrequency.QuadPart);
+
+ return msecTicks;
+#else
+
+#ifdef __CELLOS_LV2__
+ uint64_t freq=sys_time_get_timebase_frequency();
+ double dFreq=((double) freq) / 1000.0;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ SYS_TIMEBASE_GET( newTime );
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+
+ return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
+#endif //__CELLOS_LV2__
+#endif
+}
+
+ /// Returns the time in us since the last call to reset or since
+ /// the Clock was created.
+unsigned long long int btClock::getTimeMicroseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+ //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
+ LARGE_INTEGER currentTime, elapsedTime;
+
+ QueryPerformanceCounter(&currentTime);
+ elapsedTime.QuadPart = currentTime.QuadPart -
+ m_data->mStartTime.QuadPart;
+ elapsedTime.QuadPart *= 1000000;
+ elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
+
+ return (unsigned long long) elapsedTime.QuadPart;
+#else
+
+#ifdef __CELLOS_LV2__
+ uint64_t freq=sys_time_get_timebase_frequency();
+ double dFreq=((double) freq)/ 1000000.0;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET( newTime );
+
+ return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec);
+#endif//__CELLOS_LV2__
+#endif
+}
+
+unsigned long long int btClock::getTimeNanoseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+ //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
+ LARGE_INTEGER currentTime, elapsedTime;
+
+ QueryPerformanceCounter(&currentTime);
+ elapsedTime.QuadPart = currentTime.QuadPart -
+ m_data->mStartTime.QuadPart;
+ elapsedTime.QuadPart *= 1000000000;
+ elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
+
+ return (unsigned long long) elapsedTime.QuadPart;
+#else
+
+#ifdef __CELLOS_LV2__
+ uint64_t freq=sys_time_get_timebase_frequency();
+ double dFreq=((double) freq)/ 1e9;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET( newTime );
+
+ return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+#ifdef __APPLE__
+ uint64_t ticks = mach_absolute_time() - m_data->mStartTimeNano;
+ static long double conversion = 0.0L;
+ if( 0.0L == conversion )
+ {
+ // attempt to get conversion to nanoseconds
+ mach_timebase_info_data_t info;
+ int err = mach_timebase_info( &info );
+ if( err )
+ {
+ btAssert(0);
+ conversion = 1.;
+ }
+ conversion = info.numer / info.denom;
+ }
+ return (ticks * conversion);
+
+
+#else//__APPLE__
+
+#ifdef BT_LINUX_REALTIME
+ timespec ts;
+ clock_gettime(CLOCK_REALTIME,&ts);
+ return 1000000000*ts.tv_sec + ts.tv_nsec;
+#else
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1e9 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec)*1000;
+#endif //BT_LINUX_REALTIME
+
+#endif//__APPLE__
+#endif//__CELLOS_LV2__
+#endif
+}
+
+
+/// Returns the time in s since the last call to reset or since
+/// the Clock was created.
+btScalar btClock::getTimeSeconds()
+{
+ static const btScalar microseconds_to_seconds = btScalar(0.000001);
+ return btScalar(getTimeMicroseconds()) * microseconds_to_seconds;
+}
+
+#ifndef BT_NO_PROFILE
+
+
+static btClock gProfileClock;
+
+
+inline void Profile_Get_Ticks(unsigned long int * ticks)
+{
+ *ticks = (unsigned long int)gProfileClock.getTimeMicroseconds();
+}
+
+inline float Profile_Get_Tick_Rate(void)
+{
+// return 1000000.f;
+ return 1000.f;
+
+}
+
+
+/***************************************************************************************************
+**
+** CProfileNode
+**
+***************************************************************************************************/
+
+/***********************************************************************************************
+ * INPUT: *
+ * name - pointer to a static string which is the name of this profile node *
+ * parent - parent pointer *
+ * *
+ * WARNINGS: *
+ * The name is assumed to be a static pointer, only the pointer is stored and compared for *
+ * efficiency reasons. *
+ *=============================================================================================*/
+CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
+ Name( name ),
+ TotalCalls( 0 ),
+ TotalTime( 0 ),
+ StartTime( 0 ),
+ RecursionCounter( 0 ),
+ Parent( parent ),
+ Child( NULL ),
+ Sibling( NULL ),
+ m_userPtr(0)
+{
+ Reset();
+}
+
+
+void CProfileNode::CleanupMemory()
+{
+ delete ( Child);
+ Child = NULL;
+ delete ( Sibling);
+ Sibling = NULL;
+}
+
+CProfileNode::~CProfileNode( void )
+{
+ CleanupMemory();
+}
+
+
+/***********************************************************************************************
+ * INPUT: *
+ * name - static string pointer to the name of the node we are searching for *
+ * *
+ * WARNINGS: *
+ * All profile names are assumed to be static strings so this function uses pointer compares *
+ * to find the named node. *
+ *=============================================================================================*/
+CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
+{
+ // Try to find this sub node
+ CProfileNode * child = Child;
+ while ( child ) {
+ if ( child->Name == name ) {
+ return child;
+ }
+ child = child->Sibling;
+ }
+
+ // We didn't find it, so add it
+
+ CProfileNode * node = new CProfileNode( name, this );
+ node->Sibling = Child;
+ Child = node;
+ return node;
+}
+
+
+void CProfileNode::Reset( void )
+{
+ TotalCalls = 0;
+ TotalTime = 0.0f;
+
+
+ if ( Child ) {
+ Child->Reset();
+ }
+ if ( Sibling ) {
+ Sibling->Reset();
+ }
+}
+
+
+void CProfileNode::Call( void )
+{
+ TotalCalls++;
+ if (RecursionCounter++ == 0) {
+ Profile_Get_Ticks(&StartTime);
+ }
+}
+
+
+bool CProfileNode::Return( void )
+{
+ if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
+ unsigned long int time;
+ Profile_Get_Ticks(&time);
+
+ time-=StartTime;
+ TotalTime += (float)time / Profile_Get_Tick_Rate();
+ }
+ return ( RecursionCounter == 0 );
+}
+
+
+/***************************************************************************************************
+**
+** CProfileIterator
+**
+***************************************************************************************************/
+CProfileIterator::CProfileIterator( CProfileNode * start )
+{
+ CurrentParent = start;
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void CProfileIterator::First(void)
+{
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void CProfileIterator::Next(void)
+{
+ CurrentChild = CurrentChild->Get_Sibling();
+}
+
+
+bool CProfileIterator::Is_Done(void)
+{
+ return CurrentChild == NULL;
+}
+
+
+void CProfileIterator::Enter_Child( int index )
+{
+ CurrentChild = CurrentParent->Get_Child();
+ while ( (CurrentChild != NULL) && (index != 0) ) {
+ index--;
+ CurrentChild = CurrentChild->Get_Sibling();
+ }
+
+ if ( CurrentChild != NULL ) {
+ CurrentParent = CurrentChild;
+ CurrentChild = CurrentParent->Get_Child();
+ }
+}
+
+
+void CProfileIterator::Enter_Parent( void )
+{
+ if ( CurrentParent->Get_Parent() != NULL ) {
+ CurrentParent = CurrentParent->Get_Parent();
+ }
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+/***************************************************************************************************
+**
+** CProfileManager
+**
+***************************************************************************************************/
+
+
+
+
+CProfileNode gRoots[BT_QUICKPROF_MAX_THREAD_COUNT]={
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL)
+};
+
+
+CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT]=
+{
+ &gRoots[ 0], &gRoots[ 1], &gRoots[ 2], &gRoots[ 3],
+ &gRoots[ 4], &gRoots[ 5], &gRoots[ 6], &gRoots[ 7],
+ &gRoots[ 8], &gRoots[ 9], &gRoots[10], &gRoots[11],
+ &gRoots[12], &gRoots[13], &gRoots[14], &gRoots[15],
+ &gRoots[16], &gRoots[17], &gRoots[18], &gRoots[19],
+ &gRoots[20], &gRoots[21], &gRoots[22], &gRoots[23],
+ &gRoots[24], &gRoots[25], &gRoots[26], &gRoots[27],
+ &gRoots[28], &gRoots[29], &gRoots[30], &gRoots[31],
+ &gRoots[32], &gRoots[33], &gRoots[34], &gRoots[35],
+ &gRoots[36], &gRoots[37], &gRoots[38], &gRoots[39],
+ &gRoots[40], &gRoots[41], &gRoots[42], &gRoots[43],
+ &gRoots[44], &gRoots[45], &gRoots[46], &gRoots[47],
+ &gRoots[48], &gRoots[49], &gRoots[50], &gRoots[51],
+ &gRoots[52], &gRoots[53], &gRoots[54], &gRoots[55],
+ &gRoots[56], &gRoots[57], &gRoots[58], &gRoots[59],
+ &gRoots[60], &gRoots[61], &gRoots[62], &gRoots[63],
+};
+
+
+int CProfileManager::FrameCounter = 0;
+unsigned long int CProfileManager::ResetTime = 0;
+
+CProfileIterator * CProfileManager::Get_Iterator( void )
+{
+
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return 0;
+
+ return new CProfileIterator( &gRoots[threadIndex]);
+}
+
+void CProfileManager::CleanupMemory(void)
+{
+ for (int i=0;i<BT_QUICKPROF_MAX_THREAD_COUNT;i++)
+ {
+ gRoots[i].CleanupMemory();
+ }
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Start_Profile -- Begin a named profile *
+ * *
+ * Steps one level deeper into the tree, if a child already exists with the specified name *
+ * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
+ * *
+ * INPUT: *
+ * name - name of this profiling record *
+ * *
+ * WARNINGS: *
+ * The string used is assumed to be a static string; pointer compares are used throughout *
+ * the profiling code for efficiency. *
+ *=============================================================================================*/
+void CProfileManager::Start_Profile( const char * name )
+{
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return;
+
+ if (name != gCurrentNodes[threadIndex]->Get_Name()) {
+ gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node( name );
+ }
+
+ gCurrentNodes[threadIndex]->Call();
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Stop_Profile -- Stop timing and record the results. *
+ *=============================================================================================*/
+void CProfileManager::Stop_Profile( void )
+{
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return;
+
+ // Return will indicate whether we should back up to our parent (we may
+ // be profiling a recursive function)
+ if (gCurrentNodes[threadIndex]->Return()) {
+ gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Parent();
+ }
+}
+
+
+
+
+
+
+/***********************************************************************************************
+ * CProfileManager::Reset -- Reset the contents of the profiling system *
+ * *
+ * This resets everything except for the tree structure. All of the timing data is reset. *
+ *=============================================================================================*/
+void CProfileManager::Reset( void )
+{
+ gProfileClock.reset();
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return;
+ gRoots[threadIndex].Reset();
+ gRoots[threadIndex].Call();
+ FrameCounter = 0;
+ Profile_Get_Ticks(&ResetTime);
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
+ *=============================================================================================*/
+void CProfileManager::Increment_Frame_Counter( void )
+{
+ FrameCounter++;
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
+ *=============================================================================================*/
+float CProfileManager::Get_Time_Since_Reset( void )
+{
+ unsigned long int time;
+ Profile_Get_Ticks(&time);
+ time -= ResetTime;
+ return (float)time / Profile_Get_Tick_Rate();
+}
+
+#include <stdio.h>
+
+void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
+{
+ profileIterator->First();
+ if (profileIterator->Is_Done())
+ return;
+
+ float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
+ int i;
+ int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
+ for (i=0;i<spacing;i++) printf(".");
+ printf("----------------------------------\n");
+ for (i=0;i<spacing;i++) printf(".");
+ printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time );
+ float totalTime = 0.f;
+
+
+ int numChildren = 0;
+
+ for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
+ {
+ numChildren++;
+ float current_total_time = profileIterator->Get_Current_Total_Time();
+ accumulated_time += current_total_time;
+ float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
+ {
+ int i; for (i=0;i<spacing;i++) printf(".");
+ }
+ printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
+ totalTime += current_total_time;
+ //recurse into children
+ }
+
+ if (parent_time < accumulated_time)
+ {
+ //printf("what's wrong\n");
+ }
+ for (i=0;i<spacing;i++) printf(".");
+ printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
+
+ for (i=0;i<numChildren;i++)
+ {
+ profileIterator->Enter_Child(i);
+ dumpRecursive(profileIterator,spacing+3);
+ profileIterator->Enter_Parent();
+ }
+}
+
+
+
+void CProfileManager::dumpAll()
+{
+ CProfileIterator* profileIterator = 0;
+ profileIterator = CProfileManager::Get_Iterator();
+
+ dumpRecursive(profileIterator,0);
+
+ CProfileManager::Release_Iterator(profileIterator);
+}
+
+
+
+
+unsigned int btQuickprofGetCurrentThreadIndex2()
+{
+#if BT_THREADSAFE
+ return btGetCurrentThreadIndex();
+#else // #if BT_THREADSAFE
+ const unsigned int kNullIndex = ~0U;
+#ifdef _WIN32
+ #if defined(__MINGW32__) || defined(__MINGW64__)
+ static __thread unsigned int sThreadIndex = kNullIndex;
+ #else
+ __declspec( thread ) static unsigned int sThreadIndex = kNullIndex;
+ #endif
+#else
+#ifdef __APPLE__
+ #if TARGET_OS_IPHONE
+ unsigned int sThreadIndex = 0;
+ return -1;
+ #else
+ static __thread unsigned int sThreadIndex = kNullIndex;
+ #endif
+#else//__APPLE__
+#if __linux__
+ static __thread unsigned int sThreadIndex = kNullIndex;
+#else
+ unsigned int sThreadIndex = 0;
+ return -1;
+#endif
+#endif//__APPLE__
+
+#endif
+ static int gThreadCounter=0;
+
+ if ( sThreadIndex == kNullIndex )
+ {
+ sThreadIndex = gThreadCounter++;
+ }
+ return sThreadIndex;
+#endif // #else // #if BT_THREADSAFE
+}
+
+void btEnterProfileZoneDefault(const char* name)
+{
+ CProfileManager::Start_Profile( name );
+}
+void btLeaveProfileZoneDefault()
+{
+ CProfileManager::Stop_Profile();
+}
+
+
+#else
+void btEnterProfileZoneDefault(const char* name)
+{
+}
+void btLeaveProfileZoneDefault()
+{
+}
+#endif //BT_NO_PROFILE
+
+
+
+
+
+static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault;
+static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault;
+
+void btEnterProfileZone(const char* name)
+{
+ (bts_enterFunc)(name);
+}
+void btLeaveProfileZone()
+{
+ (bts_leaveFunc)();
+}
+
+btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc()
+{
+ return bts_enterFunc ;
+}
+btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc()
+{
+ return bts_leaveFunc;
+}
+
+
+void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc)
+{
+ bts_enterFunc = enterFunc;
+}
+void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc)
+{
+ bts_leaveFunc = leaveFunc;
+}
+
+CProfileSample::CProfileSample( const char * name )
+{
+ btEnterProfileZone(name);
+}
+
+CProfileSample::~CProfileSample( void )
+{
+ btLeaveProfileZone();
+}
+