/*
PIP - Platform Independent Primitives
Unix time
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see .
*/
#include "piincludes_p.h"
#include "pisystemtime.h"
#include "pitime.h"
#include
#ifdef QNX
# include
#endif
#ifndef MICRO_PIP
# include "pisystemtests.h"
#elif defined(ARDUINO)
# include
#endif
#ifdef WINDOWS
extern FILETIME __pi_ftjan1970;
long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;}
#endif
#ifdef MAC_OS
//# include
//# include
# include
//# include
extern clock_serv_t __pi_mac_clock;
#endif
#ifdef MICRO_PIP
# include
#endif
//! \addtogroup Core
//! \{
//! \class PISystemTime pisystemtime.h
//! \brief
//! \~english System time with nanosecond precision
//! \~russian Системное время с точностью до наносекунд
//!
//! \~english \section PISystemTime_sec0 Synopsis
//! \~russian \section PISystemTime_sec0 Краткий обзор
//! \~english
//! This class provide arithmetic functions for POSIX system time.
//! This time represents as seconds and nanosecons in integer formats.
//! You can take current system time with function \a PISystemTime::current(),
//! compare times, sum or subtract two times, convert time to/from
//! seconds, milliseconds, microseconds or nanoseconds.
//!
//! \~russian
//! Этот класс предоставляет арифметику для системного времени в формате POSIX.
//! Это время представлено в виде целочисленных секунд и наносекунд.
//! Можно взять текущее время с помощью метода \a PISystemTime::current(),
//! сравнивать, суммировать и вычитать времена, преобразовывать в/из
//! секунд, миллисекунд, микросекунд и наносекунд.
//!
//! \~english \section PISystemTime_sec1 Example
//! \~russian \section PISystemTime_sec1 Пример
//! \~\snippet pitimer.cpp system_time
//!
//! \}
//! \addtogroup Core
//! \{
//! \class PITimeMeasurer pisystemtime.h
//! \brief
//! \~english Time measurements
//! \~russian Измерение времени
//!
//! \~english \section PITimeMeasurer_sec0 Usage
//! \~russian \section PITimeMeasurer_sec0 Использование
//! \~english
//! Function \a reset() set time mark to current
//! system time, then functions "double elapsed_*()" returns time elapsed from this mark.
//! These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m"
//! and "s"
//!
//! \~russian
//! Метод \a reset() устанавливает текущую метку системного времени. Далее методы
//! "double elapsed_*()" возвращают время, прошедшее от установленной метки.
//! Эти методы возвращают нано, микро, милли и секунды с приставками
//! "n", "u", "m" и "s".
//!
//! \}
//! \details
//! \warning
//! \~english
//! Use this function to sleep for difference of system times or constructs system time.
//! If you call this function on system time returned with \a PISystemTime::current() thread will be sleep almost forever
//! \~russian
//! Используйте этот метод для ожидания разниц системных времен или своего времени.
//! Если метод будет вызван для системного времени \a PISystemTime::current(), то
//! ожидание будет почти бесконечным
void PISystemTime::sleep() {
piUSleep(piFloord(toMicroseconds()));
}
void PISystemTime::toTimespec(void * ts) {
#ifndef WINDOWS
((timespec*)ts)->tv_sec = seconds;
((timespec*)ts)->tv_nsec = nanoseconds;
#endif
}
PISystemTime PISystemTime::abs() const {
if (seconds < 0)
return PISystemTime(piAbsl(seconds) - 1, 1000000000l - piAbsl(nanoseconds));
else
return PISystemTime(piAbsl(seconds), piAbsl(nanoseconds));
}
PISystemTime PISystemTime::current(bool precise_but_not_system) {
#ifdef WINDOWS
if (precise_but_not_system) {
llong qpc(0);
if (__pi_perf_freq > 0) {
qpc = __PIQueryPerformanceCounter();
return PISystemTime::fromSeconds(qpc / double(__pi_perf_freq));
}
return PISystemTime();
} else {
FILETIME ft, sft;
# if (_WIN32_WINNT >= 0x0602)
GetSystemTimePreciseAsFileTime(&ft);
# else
GetSystemTimeAsFileTime(&ft);
# endif
sft.dwHighDateTime = ft.dwHighDateTime - __pi_ftjan1970.dwHighDateTime;
if (ft.dwLowDateTime < __pi_ftjan1970.dwLowDateTime) {
sft.dwLowDateTime = ft.dwLowDateTime + (0xFFFFFFFF - __pi_ftjan1970.dwLowDateTime);
sft.dwHighDateTime--;
} else
sft.dwLowDateTime = ft.dwLowDateTime - __pi_ftjan1970.dwLowDateTime;
ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime);
return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U);
}
#elif defined(MAC_OS)
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
#elif defined(MICRO_PIP)
timespec t_cur;
# ifdef ARDUINO
static const uint32_t offSetSinceEpoch_s = 1581897605UL;
uint32_t mt = millis();
t_cur.tv_sec = offSetSinceEpoch_s + (mt / 1000);
t_cur.tv_nsec = (mt - (mt / 1000)) * 1000000UL;
# else
timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
gettimeofday(&tv, NULL);
t_cur.tv_sec = tv.tv_sec;
t_cur.tv_nsec = tv.tv_usec * 1000;
# endif
#else
timespec t_cur;
clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur);
#endif
#ifndef WINDOWS
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
#endif
}
PITimeMeasurer::PITimeMeasurer() {
reset();
}
double PITimeMeasurer::elapsed_n() const {
return (PISystemTime::current(true) - t_st).toNanoseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns
#endif
;
}
double PITimeMeasurer::elapsed_u() const {
return (PISystemTime::current(true) - t_st).toMicroseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+3
#endif
;
}
double PITimeMeasurer::elapsed_m() const {
return (PISystemTime::current(true) - t_st).toMilliseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+6
#endif
;
}
double PITimeMeasurer::elapsed_s() const {
return (PISystemTime::current(true) - t_st).toSeconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+9
#endif
;
}
PISystemTime PITimeMeasurer::elapsed() const {
return (PISystemTime::current(true) - t_st);
}