ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
time.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !DOXYGEN
10# include "alib/time/time.hpp"
12#endif // !DOXYGEN
13
14using namespace std::chrono;
15
16#if ALIB_BOXING
17 ALIB_BOXING_VTABLE_DEFINE( alib::Ticks , vt_time_ticks )
18 ALIB_BOXING_VTABLE_DEFINE( alib::Ticks::Duration , vt_time_ticks_duration )
19 ALIB_BOXING_VTABLE_DEFINE( alib::DateTime , vt_time_datetime )
20 ALIB_BOXING_VTABLE_DEFINE( alib::DateTime::Duration , vt_time_datetime_duration )
21#endif
22
23namespace alib {
24
25/// This namespace of \alib provides types for calendrical date and time processing as well as
26/// for non-calendrical steady and monotonic time measurement.
27///
28/// Besides this reference documentation, further information is provided with
29/// \ref alib_mod_time "ALib Module Time - Programmer's Manual".
30namespace time {
31
32// #################################################################################################
33// Module Bootstrap/Termination
34// #################################################################################################
35#if !DOXYGEN
36namespace
37{
38 Ticks* creationTime= nullptr;
39
40# if ALIB_DEBUG
41 unsigned int initFlag= 0;
42# endif
43}
44#endif
45
47
49{
50 ALIB_ASSERT_ERROR( initFlag == 0, "TIME", "This method must not be invoked twice." )
51 ALIB_DBG(initFlag= 0x92A3EF61);
52
53 // create a ticks object that marks the time of creation of this non-camp module
54 if( !creationTime )
55 creationTime= new Ticks();
56
59 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_time_ticks_duration )
61 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_time_datetime_duration ) )
62}
63
65{
66 ALIB_ASSERT_ERROR( initFlag == 0x92A3EF61, "TIME", "Not initialized when calling shutdown." )
67 ALIB_DBG(initFlag= 1);
68 if( creationTime )
69 {
70 delete creationTime;
71 creationTime= nullptr;
72 }
73}
74
76{
77 return *creationTime;
78}
79
81
82// #################################################################################################
83// TickConverter
84// #################################################################################################
85void TickConverter::SyncClocks( int qtyRepeats )
86{
87 Ticks::TTimePoint steadyClock;
88 DateTime::TTimePoint systemClock;
89 uint64_t lastDiff= 0;
90 for( int i= 0 ; i < qtyRepeats ; ++i )
91 {
92 systemClock= system_clock::now();
93 steadyClock= steady_clock::now();
94
95 auto systemCount= systemClock.time_since_epoch().count();
96 auto steadyCount= steadyClock.time_since_epoch().count();
97
98 // This cannot be optimized, because:
99 // a) we have to use an unsigned integer, and
100 // b) we have to take into account which clock was measured first and which last. If
101 // interrupted between the calls, the difference either shrinks or increases.
102 if( systemCount < steadyCount )
103 {
104 uint64_t diff= static_cast<uint64_t >( steadyCount - systemCount );
105 if( lastDiff == 0 || diff < lastDiff )
106 {
107 steadyClockSyncTime= steadyClock;
108 systemClockSyncTime= systemClock;
109 lastDiff= diff;
110 }
111 }
112 else
113 {
114 uint64_t diff= static_cast<uint64_t >( systemCount - steadyCount );
115 if( lastDiff == 0 || diff > lastDiff )
116 {
117 steadyClockSyncTime= steadyClock;
118 systemClockSyncTime= systemClock;
119 lastDiff= diff;
120 }
121 }
122 }
123}
124
125
126
127// #################################################################################################
128// Windows OS specific: file time, system time
129// #################################################################################################
130#if defined( _WIN32 ) && !DOXYGEN
131
132// filetime_duration has the same layout as FILETIME; 100ns intervals
133using filetime_duration = duration<int64_t, std::ratio<1, 10000000> >;
134
135// January 1, 1601 (NT epoch) - January 1, 1970 (Unix epoch):
136constexpr duration<int64_t> nt_to_unix_epoch{INT64_C(-11644473600)};
137
138FILETIME DateTime::ToFileTime() const
139{
140 const auto asDuration = duration_cast<filetime_duration>( stamp.time_since_epoch() );
141 const auto withNtEpoch= asDuration - nt_to_unix_epoch;
142 const auto rawCount = withNtEpoch.count();
143
144 FILETIME result;
145 result.dwLowDateTime = static_cast<DWORD>(rawCount); // discards upper bits
146 result.dwHighDateTime = static_cast<DWORD>(rawCount >> 32);
147 return result;
148
149}
150
151ULARGE_INTEGER DateTime::ToFileTimeLI() const
152{
153 FILETIME ft= ToFileTime();
154 ULARGE_INTEGER result;
155 result.HighPart= ft.dwHighDateTime;
156 result.LowPart= ft.dwLowDateTime;
157 return result;
158}
159
160DateTime DateTime::FromFileTime( const FILETIME& fileTime )
161{
162 const filetime_duration ftDuration { static_cast<int64_t>( (static_cast<uint64_t>( fileTime.dwHighDateTime) << 32)
163 | fileTime.dwLowDateTime ) };
164 return DateTime( TTimePoint(ftDuration + nt_to_unix_epoch));
165}
166
167DateTime DateTime::FromFileTime( const ULARGE_INTEGER& ft )
168{
169 FILETIME fileTime;
170 fileTime.dwLowDateTime = ft.LowPart;
171 fileTime.dwHighDateTime = ft.HighPart;
172 return FromFileTime( fileTime );
173}
174
175SYSTEMTIME DateTime::ToSystemTime( lang::Timezone timezone ) const
176{
177 FILETIME ft= ToFileTime();
178 SYSTEMTIME result;
179 if ( timezone == lang::Timezone::UTC )
180 FileTimeToSystemTime( &ft, &result );
181 else
182 {
183 SYSTEMTIME utc;
184 FileTimeToSystemTime( &ft, &utc );
185 SystemTimeToTzSpecificLocalTime( NULL, &utc, &result );
186 }
187 return result;
188}
189
190DateTime DateTime::FromSystemTime( const SYSTEMTIME& st, lang::Timezone timezone )
191{
192 FILETIME ft;
193 if ( timezone == lang::Timezone::UTC )
194 SystemTimeToFileTime( &st, &ft );
195 else
196 {
197 SYSTEMTIME utc;
198 TzSpecificLocalTimeToSystemTime( NULL, &st, &utc);
199 SystemTimeToFileTime( &utc, &ft );
200 }
201 return DateTime::FromFileTime( ft );
202}
203#endif // defined( _WIN32 ) && !DOXYGEN
204}} // namespace [alib::time]
205
ALIB_API ULARGE_INTEGER ToFileTimeLI() const
static ALIB_API DateTime FromFileTime(const FILETIME &fileTime)
static ALIB_API DateTime FromSystemTime(const SYSTEMTIME &systemTime, lang::Timezone timezone=lang::Timezone::Local)
ALIB_API SYSTEMTIME ToSystemTime(lang::Timezone timezone=lang::Timezone::Local) const
ALIB_API FILETIME ToFileTime() const
Ticks::TTimePoint steadyClockSyncTime
Time point of steady clock of last invocation of SyncClocks.
ALIB_API void SyncClocks(int qtyRepeats=5)
Definition time.cpp:85
DateTime::TTimePoint systemClockSyncTime
Time point of system clock of last invocation of SyncClocks.
typename std::chrono::steady_clock::time_point TTimePoint
#define IF_ALIB_BOXING(...)
Definition alib.hpp:248
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
Definition vtable.inl:473
#define ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER(Identifier)
Definition vtable.inl:489
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_DBG(...)
Definition alib.hpp:390
Timezone
Denotes whether a time value represents local time or UTC.
@ UTC
Denotes UTC (coordinated universal time).
void Bootstrap()
Definition time.cpp:48
Ticks & CreationTime()
Definition time.cpp:75
void Shutdown()
Definition time.cpp:64
Definition alib.cpp:69
time::Ticks Ticks
Type alias in namespace alib.
Definition ticks.hpp:115
time::DateTime DateTime
Type alias in namespace alib.
Definition datetime.hpp:228