Base: Use std::chrono for time handling

Replace platform specific implementations with standard C++ std::chrono.
As time_t is now 64-bit on all supported systems, use it to set the clock.
This commit is contained in:
Ladislav Michl
2023-11-15 10:28:15 +01:00
parent de1305413e
commit 159fe5c21f
6 changed files with 66 additions and 229 deletions

View File

@@ -264,7 +264,6 @@ SET(FreeCADBase_CPP_SRCS
Stream.cpp
Swap.cpp
${SWIG_SRCS}
TimeInfo.cpp
Tools.cpp
Tools2D.cpp
Tools3D.cpp

View File

@@ -37,6 +37,7 @@
#include <cassert>
#include <ctime>
#include <cfloat>
#include <chrono>
#ifdef FC_OS_WIN32
#define _USE_MATH_DEFINES
#endif // FC_OS_WIN32

View File

@@ -1,105 +0,0 @@
/***************************************************************************
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <sstream>
#include <QDateTime>
#if defined(FC_OS_LINUX) || defined(__MINGW32__)
#include <sys/time.h>
#endif
#endif
#include "TimeInfo.h"
using namespace Base;
/**
* A constructor.
* A more elaborate description of the constructor.
*/
TimeInfo::TimeInfo()
{
setCurrent();
}
/**
* A destructor.
* A more elaborate description of the destructor.
*/
TimeInfo::~TimeInfo() = default;
//**************************************************************************
// separator for other implementation aspects
void TimeInfo::setCurrent()
{
// clang-format off
#if defined(FC_OS_BSD) || defined(FC_OS_LINUX) || defined(__MINGW32__)
struct timeval tv {};
gettimeofday(&tv, nullptr);
timebuffer.time = tv.tv_sec;
timebuffer.millitm = tv.tv_usec / 1000;
#elif defined(FC_OS_WIN32)
_ftime(&timebuffer);
#else
ftime(&timebuffer); // deprecated
#endif
// clang-format on
}
void TimeInfo::setTime_t(int64_t seconds)
{
timebuffer.time = seconds;
}
std::string TimeInfo::diffTime(const TimeInfo& timeStart, const TimeInfo& timeEnd)
{
std::stringstream str;
str << diffTimeF(timeStart, timeEnd);
return str.str();
}
float TimeInfo::diffTimeF(const TimeInfo& timeStart, const TimeInfo& timeEnd)
{
int64_t ds = int64_t(timeEnd.getSeconds() - timeStart.getSeconds());
int dms = int(timeEnd.getMiliseconds()) - int(timeStart.getMiliseconds());
return float(ds) + float(dms) * 0.001F;
}
TimeInfo TimeInfo::null()
{
TimeInfo ti;
ti.timebuffer = {};
return ti;
}
bool TimeInfo::isNull() const
{
return (*this) == TimeInfo::null();
}

View File

@@ -1,5 +1,6 @@
/***************************************************************************
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
* Copyright (c) 2024 Ladislav Michl <ladis@linux-mips.org> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
@@ -24,134 +25,75 @@
#ifndef BASE_TIMEINFO_H
#define BASE_TIMEINFO_H
// Std. configurations
#include <cstdio>
#if defined(FC_OS_BSD)
#include <sys/time.h>
#else
#include <sys/timeb.h>
#endif
#include <ctime>
#ifdef __GNUC__
#include <cstdint>
#endif
#include <chrono>
#include <sstream>
#include <string>
#include <FCGlobal.h>
#if defined(FC_OS_BSD)
struct timeb
{
int64_t time;
unsigned short millitm;
};
#endif
namespace Base
{
/// BaseClass class and root of the type system
class BaseExport TimeInfo
using Clock = std::chrono::system_clock;
class TimeInfo: public std::chrono::time_point<Clock>
{
private:
bool _null;
public:
/// Construction
TimeInfo();
TimeInfo()
{
setCurrent();
}
TimeInfo(const TimeInfo&) = default;
TimeInfo(TimeInfo&&) = default;
/// Destruction
~TimeInfo();
~TimeInfo() = default;
/// sets the object to the actual system time
void setCurrent();
void setTime_t(int64_t seconds);
int64_t getSeconds() const;
unsigned short getMiliseconds() const;
TimeInfo& operator=(const TimeInfo& time) = default;
TimeInfo& operator=(TimeInfo&& time) = default;
bool operator==(const TimeInfo& time) const;
bool operator!=(const TimeInfo& time) const;
bool operator<(const TimeInfo& time) const;
bool operator<=(const TimeInfo& time) const;
bool operator>=(const TimeInfo& time) const;
bool operator>(const TimeInfo& time) const;
static std::string diffTime(const TimeInfo& timeStart, const TimeInfo& timeEnd = TimeInfo());
static float diffTimeF(const TimeInfo& timeStart, const TimeInfo& timeEnd = TimeInfo());
bool isNull() const;
static TimeInfo null();
private:
// clang-format off
#if defined(_MSC_VER)
struct _timeb timebuffer;
#elif defined(__GNUC__)
struct timeb timebuffer {};
#endif
// clang-format on
};
inline int64_t TimeInfo::getSeconds() const
{
return timebuffer.time;
}
inline unsigned short TimeInfo::getMiliseconds() const
{
return timebuffer.millitm;
}
inline bool TimeInfo::operator!=(const TimeInfo& time) const
{
return (timebuffer.time != time.timebuffer.time
|| timebuffer.millitm != time.timebuffer.millitm);
}
inline bool TimeInfo::operator==(const TimeInfo& time) const
{
return (timebuffer.time == time.timebuffer.time
&& timebuffer.millitm == time.timebuffer.millitm);
}
inline bool TimeInfo::operator<(const TimeInfo& time) const
{
if (timebuffer.time == time.timebuffer.time) {
return timebuffer.millitm < time.timebuffer.millitm;
void setCurrent()
{
static_cast<std::chrono::time_point<Clock>&>(*this) = Clock::now();
_null = false;
}
return timebuffer.time < time.timebuffer.time;
}
inline bool TimeInfo::operator<=(const TimeInfo& time) const
{
if (timebuffer.time == time.timebuffer.time) {
return timebuffer.millitm <= time.timebuffer.millitm;
void setTime_t(std::time_t time)
{
static_cast<std::chrono::time_point<Clock>&>(*this) = Clock::from_time_t(time);
_null = false;
}
return timebuffer.time <= time.timebuffer.time;
}
inline bool TimeInfo::operator>=(const TimeInfo& time) const
{
if (timebuffer.time == time.timebuffer.time) {
return timebuffer.millitm >= time.timebuffer.millitm;
std::time_t getTime_t()
{
return Clock::to_time_t(*this);
}
return timebuffer.time >= time.timebuffer.time;
}
inline bool TimeInfo::operator>(const TimeInfo& time) const
{
if (timebuffer.time == time.timebuffer.time) {
return timebuffer.millitm > time.timebuffer.millitm;
static float diffTimeF(const TimeInfo& start, const TimeInfo& end = TimeInfo())
{
const std::chrono::duration<float> duration = end - start;
return duration.count();
}
return timebuffer.time > time.timebuffer.time;
}
static std::string diffTime(const TimeInfo& start, const TimeInfo& end = TimeInfo())
{
std::stringstream ss;
const std::chrono::duration<float> secs = end - start;
ss << secs.count();
return ss.str();
}
bool isNull() const
{
return _null;
}
static TimeInfo null()
{
TimeInfo ti;
ti._null = true;
return ti;
}
}; // class TimeInfo
} // namespace Base
#endif // BASE_TIMEINFO_H