Bjr, en fouinant sur DVP comme j'aime le faire je suis tombé sur ce vieux post. Je me permet de le compléter par une solution alternative en VC++ 4.0 écrite en 2003. Je crois que ça marche encore avec les versions ultérieures. C'est une horloge à la microseconde. Implémenté sous forme d'une classe dont toutes ls fonctrions membre sont inline : le code complet tient dans le .h dont je fais copie ci-dessous.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* File :
This file implements a microsecond precision clock.
We can start it (reset to zero), watch it (getting the elapsed time from start in many units)
We wan also ask it to wait until a specified time.
 
 Remark:
  In Windows,  the millisecond is the atomic time unit for the followings operations:
  * waiting without CPU usage (with Sleep)
  * getting software interuptions. In this latter case, only a precision of 10 ms is garanted in practice.
  It is always possible to get an accurate time (in microseconds) by requesting a hardware clock on the mother board (if any)
  However, it it not possible to use this clock to get sub-microseconds interrupts neither to sleep peacefully.
  The solution I implemented is to sleep peacefully the desired numbers of microseconds then to actively wath the precision clock.
----------------------------------------------------------------------------------*/
 
#pragma once
#pragma message( "Including " __FILE__ )
#define MICROCLOCK_H
 
// #include "Globals.h"
// #include "utils.h"
 
class CMicroClock {
protected:
	__int64  n_Start ; // time when start was called
	__int64  n_Watch ; // time when couter was last watched
	__int64  n_CountsPerSec ; // counter frequeny (machine dependent)
	__int64  n_llCorrection ; // elapsed time of a start-watch sequence
 
public:
	CMicroClock(void); // calculates frequency and calibrate correction factor
	__int64 Start(void); // get current time in start
	void Start(__int64 newStartValue); // Change the value of the start member
	__int64 GetCurrentCount(void); // get current time in GetCurrentCount
 
	// Results in seconds in double
	double GetDurationSec(void) ; // calculates time between start and GetCurrentCount members
	double WatchSec(void) ; // call GetCurrentCount, then calculate duration
 
	// Results in microseconds in 64 bits integer
	__int64 GetDurationMicro(void) ; // calculates time between start and GetCurrentCount members
	__int64 Watch(void) ; // call GetCurrentCount, then calculate duration
	__int64 WatchAndRestart(void) ; // call Watch,then use the watch date as new zero
 
	// Results in milli seconds in long with loss of precision (unsigned long is good because it can be mapped on a dialog)
	unsigned WatchMilliSec(void) ;
 
	// Offsets the start
	void Offset(__int64 offset) ; // add offset to Start as many times as possible but maintains (start <= watch)
 
	// Provide conversions between time units and counter
	double Count2sec (__int64 count) ;
	__int64 Count2microsec (__int64 count) ;
	__int64 Microsec2count (__int64 microsec) ;
	__int64 Sec2count (double sec) ;
 
	// wait quietly as many ms as possible with sleep,
	// then wait actively the rest of the time
	// a tolerance si set to allow sleeping a full millisecond even if some microseconds are missing
	__int64 WaitUntil(__int64 awakeTime, __int64 round = 100) ;
};
 
inline CMicroClock::CMicroClock(void) {
	// get frequency
	LARGE_INTEGER countsPerSec; // LargeIntegers are 64 bits native integers embeded in a Union designed for compatibility with systems/compilers which does not support native 64 bits integers. The QuadPart member is the native 64 bits integer.
	QueryPerformanceFrequency(&countsPerSec) ; // the current performance-counter frequency, in counts per second. 
	n_CountsPerSec = countsPerSec.QuadPart;
	if (n_CountsPerSec == 0) throw "This computer does not support high-frequency counters. Application cannot run" ;
	// Calibration
	Start();
	GetCurrentCount();
	n_llCorrection = n_Watch - n_Start ;
	// Restart in case of any use
	Start() ; 
}
 
inline __int64 CMicroClock::Start(void) {
	// Sleep(10); // Ensure we will not be interrupted by any other thread for a while
	QueryPerformanceCounter((LARGE_INTEGER*)&n_Start) ;
	return n_Start ;
}
 
inline void CMicroClock::Start(__int64 newStartValue) {
	n_Start = newStartValue ;
}
 
inline __int64 CMicroClock::GetCurrentCount(void) {
	QueryPerformanceCounter((LARGE_INTEGER*)&n_Watch) ;
	return n_Watch ;
}
 
// duration in seconds in double
inline double CMicroClock::GetDurationSec(void)  {
	return Count2sec(n_Watch - n_Start - n_llCorrection) ;
}
 
// duration in microseconds in 64 bits integer
inline __int64 CMicroClock::GetDurationMicro(void)  {
	return Count2microsec(n_Watch - n_Start - n_llCorrection) ;
}
 
inline double CMicroClock::WatchSec(void) {
	GetCurrentCount() ;
	return GetDurationSec() ;
}
 
// Convert to milli second with precision loss
inline unsigned CMicroClock::WatchMilliSec(void) {
	GetCurrentCount() ;
	return (unsigned)(GetDurationMicro() / 1000) ;
}
 
inline __int64 CMicroClock::Watch(void) {
	GetCurrentCount() ;
	return GetDurationMicro() ;
}
 
inline __int64 CMicroClock::WatchAndRestart(void) {
	__int64 r = Watch() ;
	n_Start = n_Watch ;
	return r ;
}
 
inline void CMicroClock::Offset(__int64 offset) {
	GetCurrentCount() ;
	 n_Start += offset * ((n_Watch - n_Start) / offset) ;
}
 
inline double CMicroClock::Count2sec (__int64 count) {
	static  double k = 1.0 / (double)n_CountsPerSec ;
	return (double)count * k ;
}
 
inline __int64 CMicroClock::Count2microsec (__int64 count) {
	static  __int64 million = 1000000 ;
	return (__int64)(count * million / n_CountsPerSec) ;
}
 
inline __int64 CMicroClock::Microsec2count (__int64 microsec) {
	static  __int64 million = 1000000 ;
	return  (__int64)(microsec * n_CountsPerSec / million) ;
}
 
inline __int64 CMicroClock::Sec2count (double sec) {
	return (__int64)(sec * n_CountsPerSec) ;
}
 
inline __int64 CMicroClock::WaitUntil(__int64 awakeTime, __int64 round /* = 100 */ ) {
	__int64 enter = Watch(), quit ;
	__int64 sleep_micro = awakeTime - enter ;
	unsigned sleep_ms ;
	if (sleep_micro > 1000 - round) {
		sleep_ms = max(1U,  (unsigned)(sleep_micro/1000)) ;
		Sleep(sleep_ms) ; // quiet wait, in ms
	} 
	while ((quit = Watch()) < awakeTime) ;
	return quit - enter ;
}