Get Absolute Time
1.1. 시작하기전에 ¶프로그래밍을 하다가 보면 절대적으로 순방향으로만 증가하는 시간자원이 필요할때가 많습니다.
특정 시간 구간의 소요시간을 측정한다던가 특정 주기마다 어떤 실행을 구현하려고 할때 일반적인 시계자원의 경우 시간동기가 중간에 일어나면 시간이 역방향 또는 많은 시간을 건너뛰는 상태가 발생할 수 있습니다. 이럴때 충분히 고려되지 않으면 프로그램은 의도되지 않은 동작을 일으키기 매우 쉽습니다. 여기서는 최대한 많은 Platform에서 동작가능한 절대적 순방향 시간자원에 대한 구현을 다루고자 합니다. 절대적 순방향 시간자원의 구현에 필수적인 요구사항은 다음과 같습니다.
1.2. Windows 에서의 구현 ¶#define hwport_uintmax_t ULONGLONG int __hwport_get_absolute_time_msec(hwport_uintmax_t *s_msec_ptr) { LARGE_INTEGER s_performance_frequency; LARGE_INTEGER s_performance_count; if(QueryPerformanceFrequency((LARGE_INTEGER *)(&s_performance_frequency)) != TRUE) { return(-1); } if(s_performance_frequency.QuadPart == ((LONGLONG)0)) { return(-1); } if(QueryPerformanceCounter((LARGE_INTEGER *)(&s_performance_count)) != TRUE) { return(-1); } *s_msec_ptr = ((((hwport_uintmax_t)s_performance_count.QuadPart) * ((hwport_uintmax_t)1000u)) / ((hwport_uintmax_t)s_performance_frequency.QuadPart)); return(0); } 1.3. OS X 에서의 구현 (Mach kernel 기반) ¶# include <mach/mach_time.h> #define hwport_uintmax_t unsigned long long int __hwport_get_absolute_time_msec(hwport_uintmax_t *s_msec_ptr) { mach_timebase_info_data_t s_timebase; /* mach kernel */ mach_timebase_info(&s_timebase); if(s_timebase.denom == 0) { return(-1); } *s_msec_ptr = (((hwport_uintmax_t)mach_absolute_time()) * ((hwport_uintmax_t)s_timebase.numer)) / (((hwport_uintmax_t)s_timebase.denom) * ((hwport_uintmax_t)1000000)); return(0); } 1.4. Linux(또는 Android) 에서의 구현 (librt.so 를 직접 링크하지 않고 SystemCall을 직접 사용하는 방법) ¶/* need define _GNU_SOURCE */ # include <unistd.h> # include <sys/syscall.h> # ifndef CLOCK_MONOTONIC # warning "Old glibc (< 2.3.4) does not provide this constant. We use syscall directly so this definition is safe." # define CLOCK_MONOTONIC 1 # endif # if !defined(SYS_clock_gettime) # define SYS_clock_gettime __NR_clock_gettime # endif #define hwport_uintmax_t unsigned long long int __hwport_get_absolute_time_msec(hwport_uintmax_t *s_msec_ptr) { struct timespec s_timespec; /* libc has incredibly messy way of doing this, typically requiring -lrt. We just skip all this mess */ if(syscall(SYS_clock_gettime /* __NR_clock_gettime */, (int)CLOCK_MONOTONIC, (void *)(&s_timespec)) != 0) { return(-1); } *s_msec_ptr = (((hwport_uintmax_t)s_timespec.tv_sec) * ((hwport_uintmax_t)1000u)) + (((hwport_uintmax_t)s_timespec.tv_nsec) / ((hwport_uintmax_t)1000000u)); return(0); } 1.5. Unix/BSD/Linux 계열에서의 구현 (SUv2 및 POSIX.1-2001 을 만족하는 환경, rt library를 링크해야 하는 경우가 필요할수 있음) ¶#define hwport_uintmax_t unsigned long long int __hwport_get_absolute_time_msec(hwport_uintmax_t *s_msec_ptr) { struct timespec s_timespec; /* maybe requiring -lrt */ /* SUSv2, POSIX.1-2001 */ if(clock_gettime((clockid_t)CLOCK_MONOTONIC, (struct timespec *)(&s_timespec)) != 0) { return(-1); } *s_msec_ptr = (((hwport_uintmax_t)s_timespec.tv_sec) * ((hwport_uintmax_t)1000u)) + (((hwport_uintmax_t)s_timespec.tv_nsec) / ((hwport_uintmax_t)1000000u)); return(0); } 1.6. 기타환경에서의 구현 ¶
|