Files
pip/libs/main/core/pisystemtime.cpp
2022-03-25 17:47:41 +03:00

232 lines
7.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "pisystemtime.h"
#include "pitime.h"
#include <ctime>
#ifdef QNX
# include <time.h>
#endif
#ifndef MICRO_PIP
# include "pisystemtests.h"
#elif defined(ARDUINO)
# include <Arduino.h>
#endif
#ifdef WINDOWS
extern FILETIME __pi_ftjan1970;
long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;}
#endif
#ifdef MAC_OS
//# include <mach/mach_traps.h>
//# include <mach/mach.h>
# include <mach/clock.h>
//# include <crt_externs.h>
extern clock_serv_t __pi_mac_clock;
#endif
#ifdef MICRO_PIP
# include <sys/time.h>
#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);
}