2009-11-04 7 views
15

Sto scrivendo una classe Socket portatile che supporta i timeout sia per l'invio che per la ricezione ... Per implementare questi timeout, sto usando select() .... Ma a volte ho bisogno di sapere per quanto tempo sono stato bloccato all'interno di select() quale di Naturalmente su Linux avrei implementare chiamando gettimeofday() prima e dopo che io chiamo select() e quindi utilizzando timersub() per calcolare il delta ...Cosa devo usare per sostituire gettimeofday() su Windows?

Dato che select() su Windows accetta struct timeval per il suo timeout, quale metodo dovrei utilizzato per sostituire gettimeofday () Su Windows?

risposta

18

Ho finito per trovare questa pagina: gettimeofday() in Windows [edit: Link rimosso perché ora punta a un sito pubblicitario]. Che ha un'implementazione pratica e dandy di gettimeofday() su Windows. Utilizza il metodo GetSystemTimeAsFileTime() per ottenere un orologio preciso.

Aggiornamento: Ecco un collegamento attivo [modifica: collegamento rimosso perché ora punta a un sito di pubblicità] che punta all'implementazione dell'OP a cui si fa riferimento. Si noti, inoltre, che ci sia un errore di battitura nella realizzazione collegato:

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) 
    #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 // WRONG 
#else 
    #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL // WRONG 
#endif 

I valori indicati sono mancanti un extra 0 alla fine (hanno assunto microsecondi, non il numero di intervalli di 100 nanosecondi). Questo errore di battitura è stato trovato tramite this comment in una pagina del progetto di codice Google. I valori corretti da utilizzare sono i seguenti: realizzazione

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) 
    #define DELTA_EPOCH_IN_MICROSECS 116444736000000000Ui64 // CORRECT 
#else 
    #define DELTA_EPOCH_IN_MICROSECS 116444736000000000ULL // CORRECT 
#endif 

di PostgreSQL di gettimeofday per le finestre:

/* 
* gettimeofday.c 
* Win32 gettimeofday() replacement 
* 
* src/port/gettimeofday.c 
* 
* Copyright (c) 2003 SRA, Inc. 
* Copyright (c) 2003 SKC, Inc. 
* 
* Permission to use, copy, modify, and distribute this software and 
* its documentation for any purpose, without fee, and without a 
* written agreement is hereby granted, provided that the above 
* copyright notice and this paragraph and the following two 
* paragraphs appear in all copies. 
* 
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 
* LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 
* DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED 
* OF THE POSSIBILITY OF SUCH DAMAGE. 
* 
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
* A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS 
* IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, 
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
*/ 

#include "c.h" 

#include <sys/time.h> 


/* FILETIME of Jan 1 1970 00:00:00. */ 
static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL); 

/* 
* timezone information is stored outside the kernel so tzp isn't used anymore. 
* 
* Note: this function is not for Win32 high precision timing purpose. See 
* elapsed_time(). 
*/ 
int 
gettimeofday(struct timeval * tp, struct timezone * tzp) 
{ 
    FILETIME file_time; 
    SYSTEMTIME system_time; 
    ULARGE_INTEGER ularge; 

    GetSystemTime(&system_time); 
    SystemTimeToFileTime(&system_time, &file_time); 
    ularge.LowPart = file_time.dwLowDateTime; 
    ularge.HighPart = file_time.dwHighDateTime; 

    tp->tv_sec = (long) ((ularge.QuadPart - epoch)/10000000L); 
    tp->tv_usec = (long) (system_time.wMilliseconds * 1000); 

    return 0; 
} 
+11

Il collegamento è interrotto. –

+1

Anche il secondo collegamento è stato interrotto. – Tom

+0

Ecco un collegamento al codice rilevante da PostgreSQL: http://git.postgresql.org/gitweb/?p=postgresql.git; a = blob; f = src/port/gettimeofday.c; h = 75a91993b74414c0a1c13a2a09ce739cb8aa8a08; hb = HEAD – Tom

4

ne dite:

unsigned long start = GetTickCount(); 
// stuff that needs to be timed 
unsigned long delta = GetTickCount() - start; 

GetTickCount() non è molto preciso, ma probabilmente funzionerà bene. Se vedi intervalli di 0, 16 o 31 millisecondi, prova a cronometrare su intervalli più lunghi o usa una funzione più precisa come timeGetTime.

Cosa faccio di solito è questo:

unsigned long deltastack; 
int samples = 0; 
float average; 

unsigned long start = GetTickCount(); 
// stuff that needs to be timed 
unsigned long delta = GetTickCount() - start; 

deltastack += delta; 
if (samples++ == 10) 
{ 
    // total time divided by amount of samples 
    average = (float)deltastack/10.f; 
    deltastack = 0; 
    samples = 0; 
} 
+3

Rollover GetTicksCount ogni ~ 45,7 giorni. –

+11

@Shay: quando hai visto Windows per oltre 45 giorni di fila? OK, sì che non era necessario ... –

+0

[Funzione GetTickCount] (https://msdn.microsoft.com/pt-br/library/windows/desktop/ms724408%28v=vs.85%29.aspx) - Recupera il numero di millisecondi che sono trascorsi dall'inizio del sistema, fino a 49,7 giorni. – Dinei

1

Nel tuo caso vorrei usare la piattaforma indipendente std::clock

+0

Questa funzione non restituisce un riferimento temporale assoluto. – chmike

+0

@chmike non ha detto di aver bisogno di un riferimento temporale assoluto –

1

È possibile controllare QueryPerformanceCounter e QueryPerformanceFrequency. Questi sono molto alta risoluzione- fino a un tick per dieci cicli su alcuni hardware- timer.