|
|
Motivation
A programmer often finds himself in a situation where he needs to time
the execution of a piece of code.
The StopWatch class, below, uses Windows high-performance counters to measure the time (in milliseconds)
that elapsed between the invocations of its start() and stop() member functions.
The StopWatch class
The body of class StopWatch is quite
straight-forward.
On the other hand, first part of this code snip, employs a quite
unusual hack:
Instead of using a #include <windows.h> directive to get the declarations of the four Win32 API functions
used by the class, the programmer decided to hard-code these declarations into the program.
- The main advantage: The code will perfectly compile and link even if the Microsoft's platform SDK package
is not present.
Given that these functions are implemented in
kernel32.dll, which is an integral part of any Windows installation,
there in no danger of getting a "missing dll" error at run-time.
- A slight risk: The code will stop working (a link-time error) should the declarations
in
windows.h change.
However, based on the highly convservative approach exhibited by Microsoft (over the years, just a few APIs were
changed in a non-backward compatible manner), we can estimate that these declarations will remain stable for quite
a long time.
#define WINBASEAPI
#define WINAPI __stdcall
#define IN
#define OUT
#define VOID void
typedef unsigned long DWORD;
typedef void *HANDLE;
typedef long LONG;
typedef int BOOL;
typedef __int64 LONGLONG;
typedef union _LARGE_INTEGER
{
struct
{
DWORD LowPart;
LONG HighPart;
} unused;
struct
{
DWORD LowPart;
LONG HighPart;
} u;
LONGLONG QuadPart;
} LARGE_INTEGER;
#ifdef __cplusplus
extern "C" {
#endif
WINBASEAPI BOOL WINAPI QueryPerformanceCounter(OUT LARGE_INTEGER *lpPerformanceCount);
WINBASEAPI BOOL WINAPI QueryPerformanceFrequency(OUT LARGE_INTEGER *lpFrequency);
WINBASEAPI DWORD WINAPI SetThreadAffinityMask(IN HANDLE hThread,IN DWORD dwThreadAffinityMask);
WINBASEAPI HANDLE WINAPI GetCurrentThread(VOID);
#ifdef __cplusplus
}
#endif
struct StopWatch
{
LARGE_INTEGER start_, end_;
LARGE_INTEGER freq_;
StopWatch() { start(); }
void start()
{
SetThreadAffinityMask(GetCurrentThread(), 1);
QueryPerformanceFrequency(&freq_);
QueryPerformanceCounter(&start_);
}
void stop()
{
QueryPerformanceCounter(&end_);
}
int resultMillis()
{
return 1000 * (end_.QuadPart - start_.QuadPart) / (double)freq_.QuadPart;
}
};
|
|