IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez C++ Discussion :

[C++][SOURCE] Un "clock" réel, à la microseconde près


Sujet :

Contribuez C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Avatar de ol9245
    Homme Profil pro
    Chercheur
    Inscrit en
    Avril 2007
    Messages
    985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Avril 2007
    Messages : 985
    Billets dans le blog
    1
    Par défaut [C++][SOURCE] Un "clock" réel, à la microseconde près
    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 ;
    }

  2. #2
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    C'est du C++ donc je mets de côté si un jour quelqu'un est motivé pour faire une page sources C++


Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo