Sign in to follow this  
AndreiVictor

[C++] Since yesterday, my QueryPerformanceFrequency crashes my game. [SOLVED]

Recommended Posts

Ok, this has been bugging me since yesterday. I don't know why exactly my Timer class which uses QPC and QPF isn't working anymore. QueryPerformanceFrequency causes my program to crash. It was ok for years before yesterday, but now it just won't work. I've tried on a different workstation and still it has that problem. It wasn't like that before. I'm thinking it has to do with time and the CPU hardware, that I might have tapped into something, or I just didn't see for many years what was wrong with my code. Can anyone help me on this one? Here are my simple small sample codes. main.cpp
#include "Timer.h"
#include <iostream>

int main()
{
	Timer * timer = new Timer();

	if( !timer )
	{
		std::cout << "No timer was created.\n";
		return 1;
	}

	std::cout << "Time is: " << timer->GetTime() << std::endl;
	return 0;
}



types.h
////////////////////////////////////////////////////////////////////////////////
/// PGEX Types Header
/// - AOV 080202
/// This is header file containing definitions, type-definitions, enumerations,
/// literals, constants and other fundamental data types.
////////////////////////////////////////////////////////////////////////////////

#ifndef PGEX_TYPES_H
#define PGEX_TYPES_H


//PREPROCESSOR DEFINITIONS//////////////////////////////////////////////////////
#if defined( _WIN32 ) & !defined( _CRT_SECURE_NO_DEPRECATE )
    #define _CRT_SECURE_NO_DEPRECATE
#endif


//LITERALS//////////////////////////////////////////////////////////////////////
#ifndef TRUE
#define TRUE    1
#endif

#ifndef FALSE
#define FALSE   0
#endif

#define ENUMPAD             0x7fffffff


//CONSTANTS/////////////////////////////////////////////////////////////////////
#define PGEX_BUFFERLENGTH   1024

#if !defined( _WIN32 )
    #ifndef WINAPI
	    #define WINAPI
    #endif

    #ifndef APIENTRY
	    #define APIENTRY
    #endif

    #ifndef NULL
	    #define NULL 0
    #endif
#endif


//TYPE DEFINITIONS//////////////////////////////////////////////////////////////
#include <string>

#ifndef _WIN32
typedef struct tagRECT
{
    S64 left;
    S64 top;
    S64 right;
    S64 bottom;
} RECT, *PRECT;
#endif

typedef unsigned    char    U8;
typedef signed      char    S8;
typedef unsigned    short   U16;
typedef signed      short   S16;
typedef unsigned    int     U32;
typedef signed      int     S32;
typedef unsigned    long    U64;            // __int64
typedef signed      long    S64;
typedef float               F32;
typedef double              F64;
typedef U8                  BYTE;
typedef size_t              MEMSIZE;
typedef char *              CSTRING;
#define PGEBOOL             bool            // if boolean type does not exist, use U32
#define STRING              std::string     // may subject to change if STL is to be replaced
#define MAP                 std::map        // may subject to change if STL is to be replaced
#define MULTIMAP            std::multimap   // may subject to change if STL is to be replaced
#define PAIR                std::pair       // may subject to change if STL is to be replaced
#define LIST                std::list       // may subject to change if STL is to be replaced

#endif



Timer.h
////////////////////////////////////////////////////////////////////////////////
/// Engine Timer Header
/// - AOV 080204
/// This utility class can be used to get time metrics. Normally used in
/// performance measurement or timing operations.
////////////////////////////////////////////////////////////////////////////////

#ifndef PGEX_TIMER_H
#define PGEX_TIMER_H


//LIBRARIES/////////////////////////////////////////////////////////////////////
#include <windows.h>
#include "types.h"


//STRUCTURES AND CLASSES////////////////////////////////////////////////////////
class Timer
{
public:
    ////////////////////////////////////////////////////////////////////////////
    /// Constructor
    /// Creates and instance of this class.
    ////////////////////////////////////////////////////////////////////////////
	Timer();

    ////////////////////////////////////////////////////////////////////////////
    /// Destructor
    /// Closing procedure of this class when destroyed.
    ////////////////////////////////////////////////////////////////////////////
	~Timer();

    ////////////////////////////////////////////////////////////////////////////
    /// GetTime method
    /// Updates the timer to the recent time and returns the time.
    /// @return the time when the engine started in seconds.
    ////////////////////////////////////////////////////////////////////////////
	F32 GetTime();

    ////////////////////////////////////////////////////////////////////////////
    /// GetRecentTime method
    /// Retrieve the recent time in seconds. This does not modify the internal
    /// timer.
    /// @return the time in seconds the last GetTime method was called.
    ////////////////////////////////////////////////////////////////////////////
	F32 GetRecentTime();

    ////////////////////////////////////////////////////////////////////////////
    /// GetLastTime method
    /// Retrieve the previous time recorded.
    /// @return the time in seconds of the time recorded before the last time
    /// GetTime method was called.
    ////////////////////////////////////////////////////////////////////////////
	F32 GetLastTime();

    ////////////////////////////////////////////////////////////////////////////
    /// GetTimeDifference method
    /// The time difference from the last time GetTime called to this recent
    /// time the GetTime called.
    /// @return the time difference in seconds.
    ////////////////////////////////////////////////////////////////////////////
	F32 GetTimeDifference();

protected:
	U64     m_nRecentTime;      ///< The latest time GetTime method was called.
	U64     m_nLastTime;        ///< The previous recent time recorded.
	F32     m_fSecsPerCount;    ///< The frequency of the performance counter to convert to the desired time unit.
};


#endif



Timer.cpp
#include "Timer.h"


Timer::Timer()
: m_nLastTime( 0 ), m_nRecentTime( 0 )
{
    // Get the frequency of the performance counter in counts per sec.
    // We need the time unit than the count so we invert it.
    // This will become a value that will be used to convert time into
    // time units.
	U64 frequency = 0;

	if( QueryPerformanceFrequency(
		reinterpret_cast< LARGE_INTEGER * >( &frequency ) ) == 0 )
    {
        // something is wrong!
    }

    m_fSecsPerCount = 1.0f / frequency;
}


Timer::~Timer()
{
}


F32 Timer::GetTime()
{
    // The recent time before becomes the last time, and then we update the
    // recent time to the real recent time now. This also returns the recent
    // time in seconds.
	m_nLastTime = m_nRecentTime;
	QueryPerformanceCounter(
		reinterpret_cast< LARGE_INTEGER * >( &m_nRecentTime ) );
	return m_nRecentTime * m_fSecsPerCount;
}


F32 Timer::GetRecentTime()
{
    // Return the recent time in seconds without modifying the timer.
	return m_nRecentTime * m_fSecsPerCount;
}


F32 Timer::GetLastTime()
{
    // Return the previous time recorded in seconds.
	return m_nLastTime * m_fSecsPerCount;
}


F32 Timer::GetTimeDifference()
{
    // Return the difference of the last two calls of GetTime in seconds.
	return ( m_nRecentTime - m_nLastTime ) * m_fSecsPerCount;
}



That's how I code really. Hope you can bear the comments. [Edited by - AndreiVictor on June 22, 2009 5:06:44 AM]

Share this post


Link to post
Share on other sites
>> typedef unsigned long U64; // __int64

unsigned long is 32 bits. What you want is either "unsigned __int64" or "unsigned long long"


Share this post


Link to post
Share on other sites
Hi quasar3d.

Thanks for the reply. That worked. I thought it was just that simple change.

My question to you know is that is __int64 a cross-platform datatype?

I assuming my S64 type definition is incorrect so I change it to signed __int64?

Share this post


Link to post
Share on other sites
_int64 may not be cross platform.
the standard alias for this type is long long
so you should do: typedef unsigned long long U64;

although you should use a long long ( or _int64 ) to query both PF and PC

Share this post


Link to post
Share on other sites
If you are including <windows.h> then you should use LARGE_INTEGER type for variable that you pass for QPC or QPF functions. To access it as 64 bit integer use QuadPart member of LARGE_INTEGER structure.

__int64 is not cross-platform type. It is Microsoft Visual C++ specific type. Afaik GCC does not have such type at all.

Share this post


Link to post
Share on other sites
" If you are including <windows.h> then you should use LARGE_INTEGER type for variable that you pass for QPC or QPF functions. To access it as 64 bit integer use QuadPart member of LARGE_INTEGER structure. "

Yes, it's true. Although I would prefer to use long long type since it is more natural and not a "managed" one. The only thing you have to do to get the same results is a type cast in both QPF and QPC.
Is goes like this:

QueryPerformanceFrequency( (LARGE_INTEGER*) &this->Your_longlong_var );

" __int64 is not cross-platform type. It is Microsoft Visual C++ specific type. Afaik GCC does not have such type at all. "

Yes, again you are correct, but if he is using QPF and QPC he is tied to windows so there's no problem to use _int64.

Share this post


Link to post
Share on other sites
The MSDN library has this to say:

".The types __int8, __int16, and __int32 are synonyms for the ANSI types that have the same size, and are useful for writing portable code that behaves identically across multiple platforms. The __int8 data type is synonymous with type char, __int16 is synonymous with type short, and __int32 is synonymous with type int. The __int64 type has no ANSI equivalent."

All these types are MICROSOFT-SPECIFIC. In other words, to answer your question __int64 is not cross-platform, you will have to find the equivalent of this on the platform you are compiling.

So for example on linux, look here :
http://linux.die.net/man/3/uint64_t

Look in header files around a bit and all the best. ;-)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this