diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index ef1fd1a..6dd52ac 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -12,8 +12,11 @@ SET( HEADERS # Make sure to add the appropriate stopwatch files... SET( HEADERS ${HEADERS} "src/StopWatch.h" ) -IF( MSVC ) + +IF( WIN32 ) SET( SOURCES ${SOURCES} "src/StopWatchWin32.cpp" ) +ELSEIF( APPLE ) + SET( SOURCES ${SOURCES} "src/StopWatchOSX.cpp" ) ELSE() SET( SOURCES ${SOURCES} "src/StopWatchUnix.cpp" ) ENDIF() diff --git a/Core/src/StopWatch.h b/Core/src/StopWatch.h index ceba41c..7c65d25 100755 --- a/Core/src/StopWatch.h +++ b/Core/src/StopWatch.h @@ -15,15 +15,20 @@ // //-------------------------------------------------------------------------------------- -#pragma once - -#include "TexCompTypes.h" +// Forward declare the private implementation of the class that will actually implement +// the timing features. This class is defined in each module depending on the platform... +class StopWatchImpl; // A simple stopwatch class using Windows' high-resolution performance counters. class StopWatch { public: StopWatch(); + StopWatch(const StopWatch &); + + ~StopWatch(); + + StopWatch &operator=(const StopWatch &); void Start(); void Stop(); @@ -34,8 +39,5 @@ public: double TimeInMicroseconds() const; private: - uint64 frequency; - uint64 start; - uint64 stop; - int32_ptr affinityMask; + StopWatchImpl *impl; }; diff --git a/Core/src/StopWatchOSX.cpp b/Core/src/StopWatchOSX.cpp new file mode 100644 index 0000000..2aeb971 --- /dev/null +++ b/Core/src/StopWatchOSX.cpp @@ -0,0 +1,67 @@ +#include "StopWatch.h" +#include "TexCompTypes.h" + +#include +#include +#include + +class StopWatchImpl { +public: + uint64 start; + + double resolution; + double duration; + + StopWatchImpl() { + mach_timebase_info_data_t info; + mach_timebase_info(&info); + + resolution = double(info.numer) / double(info.denom); + resolution *= 1e-9; + } +}; + +StopWatch::StopWatch(const StopWatch &other) { + impl = new StopWatchImpl(); + memcpy(impl, other.impl, sizeof(StopWatchImpl)); +} + +StopWatch &StopWatch::operator=(const StopWatch &other) { + if(impl) { + delete impl; + } + impl = new StopWatchImpl(); + memcpy(impl, other.impl, sizeof(StopWatchImpl)); +} + +StopWatch::~StopWatch() { + delete impl; +} + +StopWatch::StopWatch() : impl(new StopWatchImpl) { + Reset(); +} + +void StopWatch::Start() { + impl->start = mach_absolute_time(); +} + +void StopWatch::Stop() { + impl->duration = impl->resolution * (double(mach_absolute_time()) - impl->start); +} + +void StopWatch::Reset() { + impl->start = impl->duration = 0.0; +} + +double StopWatch::TimeInSeconds() const { + return impl->duration; +} + +double StopWatch::TimeInMilliseconds() const { + return impl->duration * 1000; +} + +double StopWatch::TimeInMicroseconds() const { + return impl->duration * 1000000; +} diff --git a/Core/src/StopWatchUnix.cpp b/Core/src/StopWatchUnix.cpp index ad1800f..4f353ba 100644 --- a/Core/src/StopWatchUnix.cpp +++ b/Core/src/StopWatchUnix.cpp @@ -1,29 +1,62 @@ #include "StopWatch.h" +#include "TexCompTypes.h" -StopWatch::StopWatch() { +#include +#include +#include +class StopWatchImpl { +public: + timespec ts; + + double timer; + double duration; +}; + +StopWatch::StopWatch(const StopWatch &other) { + impl = new StopWatchImpl(); + memcpy(impl, other.impl, sizeof(StopWatchImpl)); +} + +StopWatch &StopWatch::operator=(const StopWatch &other) { + if(impl) { + delete impl; + } + impl = new StopWatchImpl(); + memcpy(impl, other.impl. sizeof(StopWatchImpl)); +} + +StopWatch::~StopWatch() { + delete impl; +} + +StopWatch::StopWatch() : impl(new StopWatchImpl) { + Reset(); } void StopWatch::Start() { - + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(impl->ts)); + impl->timer = double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec); } void StopWatch::Stop() { - + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(impl->ts)); + impl->duration = -(impl->timer) + (double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec)); } void StopWatch::Reset() { - + impl->timer = impl->duration = 0.0; + memset(impl->ts, 0, sizeof(timespec)); } double StopWatch::TimeInSeconds() const { - + return impl->duration; } double StopWatch::TimeInMilliseconds() const { - + return impl->duration * 1000; } double StopWatch::TimeInMicroseconds() const { - + return impl->duration * 1000000; } diff --git a/Core/src/StopWatchWin32.cpp b/Core/src/StopWatchWin32.cpp index b8e2510..1937e31 100755 --- a/Core/src/StopWatchWin32.cpp +++ b/Core/src/StopWatchWin32.cpp @@ -16,91 +16,113 @@ //-------------------------------------------------------------------------------------- #include "StopWatch.h" +#include "TexCompTypes.h" + #include -// Initialize member variables. -StopWatch::StopWatch() : - frequency(0), - start(0), - stop(0), - affinityMask(0) -{ - // Initialize the performance counter frequency. - LARGE_INTEGER perfQuery; - BOOL supported = QueryPerformanceFrequency(&perfQuery); - assert(supported == TRUE); - this->frequency = perfQuery.QuadPart; +class StopWatchImpl { + uint64 frequency; + uint64 start; + uint64 stop; + uintptr affinityMask; + + StopWatchImpl() : + start(0), stop(0), affinityMask(0) + { + // Initialize the performance counter frequency. + LARGE_INTEGER perfQuery; + BOOL supported = QueryPerformanceFrequency(&perfQuery); + assert(supported == TRUE); + this->frequency = perfQuery.QuadPart; + } +}; + +StopWatch::StopWatch(const StopWatch &other) { + impl = new StopWatchImpl(); + memcpy(impl, other.impl, sizeof(StopWatchImpl)); +} + +StopWatch &StopWatch::operator=(const StopWatch &other) { + if(impl) { + delete impl; + } + impl = new StopWatchImpl(); + memcpy(impl, other.impl. sizeof(StopWatchImpl)); +} + +StopWatch::~StopWatch() { + delete impl; } // Start the stopwatch. void StopWatch::Start() { - // MSDN recommends setting the thread affinity to avoid bugs in the BIOS and HAL. - // Create an affinity mask for the current processor. - affinityMask = (DWORD_PTR)1 << GetCurrentProcessorNumber(); - HANDLE currThread = GetCurrentThread(); - DWORD_PTR prevAffinityMask = SetThreadAffinityMask(currThread, affinityMask); - assert(prevAffinityMask != 0); + // MSDN recommends setting the thread affinity to avoid bugs in the BIOS and HAL. + // Create an affinity mask for the current processor. + impl->affinityMask = (DWORD_PTR)1 << GetCurrentProcessorNumber(); + HANDLE currThread = GetCurrentThread(); + DWORD_PTR prevAffinityMask = SetThreadAffinityMask(currThread, impl->affinityMask); + assert(prevAffinityMask != 0); - // Query the performance counter. - LARGE_INTEGER perfQuery; - BOOL result = QueryPerformanceCounter(&perfQuery); - assert(result); - start = perfQuery.QuadPart; + // Query the performance counter. + LARGE_INTEGER perfQuery; + BOOL result = QueryPerformanceCounter(&perfQuery); + assert(result); + impl->start = perfQuery.QuadPart; - // Restore the thread's affinity mask. - prevAffinityMask = SetThreadAffinityMask(currThread, prevAffinityMask); - assert(prevAffinityMask != 0); + // Restore the thread's affinity mask. + prevAffinityMask = SetThreadAffinityMask(currThread, prevAffinityMask); + assert(prevAffinityMask != 0); } // Stop the stopwatch. void StopWatch::Stop() { - // MSDN recommends setting the thread affinity to avoid bugs in the BIOS and HAL. - // Use the affinity mask that was created in the Start function. - HANDLE currThread = GetCurrentThread(); - DWORD_PTR prevAffinityMask = SetThreadAffinityMask(currThread, affinityMask); - assert(prevAffinityMask != 0); + // MSDN recommends setting the thread affinity to avoid bugs in the BIOS and HAL. + // Use the affinity mask that was created in the Start function. + HANDLE currThread = GetCurrentThread(); + DWORD_PTR prevAffinityMask = SetThreadAffinityMask(currThread, impl->affinityMask); + assert(prevAffinityMask != 0); - // Query the performance counter. - LARGE_INTEGER perfQuery; - BOOL result = QueryPerformanceCounter(&perfQuery); - assert(result); - stop = perfQuery.QuadPart; + // Query the performance counter. + LARGE_INTEGER perfQuery; + BOOL result = QueryPerformanceCounter(&perfQuery); + assert(result); + impl->stop = perfQuery.QuadPart; - // Restore the thread's affinity mask. - prevAffinityMask = SetThreadAffinityMask(currThread, prevAffinityMask); - assert(prevAffinityMask != 0); + // Restore the thread's affinity mask. + prevAffinityMask = SetThreadAffinityMask(currThread, prevAffinityMask); + assert(prevAffinityMask != 0); } // Reset the stopwatch. void StopWatch::Reset() { - start = 0; - stop = 0; - affinityMask = 0; + impl->start = 0; + impl->stop = 0; + impl->affinityMask = 0; } // Get the elapsed time in seconds. double StopWatch::TimeInSeconds() const { - // Return the elapsed time in seconds. - assert((stop - start) > 0); - return double(stop - start) / double(frequency); + // Return the elapsed time in seconds. + assert((impl->stop - impl->start) > 0); + return double(impl->stop - impl->start) / double(frequency); } // Get the elapsed time in milliseconds. double StopWatch::TimeInMilliseconds() const { - // Return the elapsed time in milliseconds. - assert((stop - start) > 0); - return double(stop - start) / double(frequency) * 1000.0; + // Return the elapsed time in milliseconds. + assert((impl->stop - impl->start) > 0); + return double(impl->stop - impl->start) / double(frequency) * 1000.0; } // Get the elapsed time in microseconds. double StopWatch::TimeInMicroseconds() const { - // Return the elapsed time in microseconds. - assert((stop - start) > 0); - return double(stop - start) / double(frequency) * 1000000.0; + // Return the elapsed time in microseconds. + assert((impl->stop - impl->start) > 0); + return double(impl->stop - impl->start) / double(impl->frequency) * 1000000.0; }