Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix time handling #173

Merged
merged 2 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/on_pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ jobs:
cd ThreadSanitized
ctest -VV

build_linux_clang_cpp20:
name: Build on Linux with Clang, C++20
build_linux_clang_cpp17:
name: Build on Linux with Clang, C++17
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -114,7 +114,7 @@ jobs:
cd Clang
export CC=$(which clang)
export CXX=$(which clang++)
cmake -DCMAKE_CXX_STANDARD=20 ..
cmake -DCMAKE_CXX_STANDARD=17 ..
- name: Build
run: |
cd Clang
Expand Down Expand Up @@ -181,7 +181,7 @@ jobs:
run: |
mkdir Release
cd Release
cmake -DCMAKE_CXX_STANDARD=17 ..
cmake -DCMAKE_CXX_STANDARD=20 ..
make -j2 VERBOSE=1
- name: Test
run: |
Expand Down
65 changes: 36 additions & 29 deletions include/binlog/Time.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,36 @@ std::chrono::nanoseconds clockToNsSinceEpoch(const ClockSync& clockSync, std::ui
*/
void nsSinceEpochToBrokenDownTimeUTC(std::chrono::nanoseconds sinceEpoch, BrokenDownTime& dst);

/** Get the duration elapsed since the UNIX epoch in UTC (no leaps seconds) */
inline
#ifdef __linux__
std::chrono::nanoseconds
#else
std::chrono::system_clock::duration
#endif
clockSinceEpoch()
{
// Depending on how libstdc++ is built (_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL),
// system_clock::now() can result in a clock_gettime syscall,
// which is really slow compared to the vsyscall equivalent.
// Call clock_gettime unconditionally on linux:
#ifdef __linux__
struct timespec ts{};
clock_gettime(CLOCK_REALTIME, &ts);
return std::chrono::nanoseconds{
std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}
};
#else
return std::chrono::system_clock::now().time_since_epoch();
#endif
}

/** Get the number of clock ticks since the UNIX epoch in UTC (no leaps seconds) */
inline std::uint64_t clockNow()
{
return std::uint64_t(clockSinceEpoch().count());
}

/**
* Create a ClockSync corresponding to std::chrono::system_clock.
*
Expand All @@ -67,11 +97,10 @@ void nsSinceEpochToBrokenDownTimeUTC(std::chrono::nanoseconds sinceEpoch, Broken
inline ClockSync systemClockSync()
{
using Clock = std::chrono::system_clock;
static_assert(Clock::period::num == 1, "Clock measures integer fractions of a second");

const auto now = Clock::now();
const auto since_epoch = now.time_since_epoch();
const std::time_t now_tt = Clock::to_time_t(now);
const auto since_epoch = clockSinceEpoch();
const auto now_tp = Clock::time_point(std::chrono::duration_cast<Clock::duration>(since_epoch));
const std::time_t now_tt = Clock::to_time_t(now_tp);

std::tm now_tm{};
#ifdef _WIN32
Expand All @@ -98,12 +127,9 @@ inline ClockSync systemClockSync()
tzName[0] = 0;
}

// on linux, clock_gettime is used directly
#ifdef __linux__
const uint64_t frequency = 1'000'000'000; // nanoseconds
#else
const uint64_t frequency = std::uint64_t(Clock::period::den);
#endif
using Period = decltype(since_epoch)::period;
static_assert(Period::num == 1, "Clock measures integer fractions of a second");
const uint64_t frequency = std::uint64_t(Period::den);

return ClockSync{
std::uint64_t(since_epoch.count()),
Expand All @@ -114,25 +140,6 @@ inline ClockSync systemClockSync()
};
}

/** Get the number of nanoseconds since the UNIX epoch in UTC (no leaps seconds) */
inline std::uint64_t clockNow()
{
// Depending on how libstdc++ is built (_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL),
// system_clock::now() can result in a clock_gettime syscall,
// which is really slow compared to the vsyscall equivalent.
// Call clock_gettime unconditionally on linux:
#ifdef __linux__
struct timespec ts{};
clock_gettime(CLOCK_REALTIME, &ts);
const std::chrono::nanoseconds nanos{
std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}
};
return std::uint64_t(nanos.count());
#else
return std::uint64_t(std::chrono::system_clock::now().time_since_epoch().count());
#endif
}

} // namespace binlog

#endif // BINLOG_TIME_HPP
Loading