From: Joel Rosdahl Date: Sun, 5 Oct 2025 13:24:17 +0000 (+0200) Subject: refactor: Use std::chrono instead of custom classes X-Git-Tag: v4.13~139 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df53a450654e3beba409f59888b9fa2617b44b97;p=thirdparty%2Fccache.git refactor: Use std::chrono instead of custom classes --- diff --git a/src/ccache/ccache.cpp b/src/ccache/ccache.cpp index b6723321..e95ac6b7 100644 --- a/src/ccache/ccache.cpp +++ b/src/ccache/ccache.cpp @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include @@ -65,7 +64,6 @@ #include #include #include -#include #include #include #include @@ -96,6 +94,8 @@ namespace fs = util::filesystem; +using namespace std::literals::chrono_literals; + using core::Statistic; using util::DirEntry; @@ -223,21 +223,19 @@ prepare_debug_path(const fs::path& cwd, // trying to open the path for writing. std::ignore = fs::create_directories(prefix.parent_path()); - char timestamp[100]; + std::string timestamp; const auto tm = util::localtime(time_of_invocation); if (tm) { - (void)strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", &*tm); + char t[100]; + (void)strftime(t, sizeof(t), "%Y%m%d_%H%M%S", &*tm); + timestamp = t; } else { - (void)snprintf( - timestamp, - sizeof(timestamp), - "%llu", - static_cast(time_of_invocation.sec())); + timestamp = std::to_string(util::sec(time_of_invocation)); } return FMT("{}.{}_{:06}.ccache-{}", prefix, timestamp, - time_of_invocation.nsec_decimal_part() / 1000, + util::nsec_part(time_of_invocation) / 1000, suffix); } @@ -1124,7 +1122,7 @@ rewrite_stdout_from_compiler(const Context& ctx, util::Bytes&& stdout_data) static std::string format_epoch_time(const util::TimePoint& tp) { - return FMT("{}.{:09}", tp.sec(), tp.nsec_decimal_part()); + return FMT("{}.{:09}", util::sec(tp), util::nsec_part(tp)); } static bool @@ -1146,8 +1144,7 @@ source_file_is_too_new(const Context& ctx, const fs::path& path) // A relatively small safety margin is used in this case to make things safe // on common filesystems while also not bailing out when creating a source // file reasonably close in time before the compilation. - const util::Duration min_age(0, 100'000'000); // 0.1 s - util::TimePoint deadline = ctx.time_of_invocation + min_age; + util::TimePoint deadline = ctx.time_of_invocation + 100ms; DirEntry dir_entry(path); @@ -1495,7 +1492,7 @@ hash_compiler(const Context& ctx, } else if (ctx.config.compiler_check() == "mtime") { hash.hash_delimiter("cc_mtime"); hash.hash(dir_entry.size()); - hash.hash(dir_entry.mtime().nsec()); + hash.hash(util::nsec_tot(dir_entry.mtime())); } else if (util::starts_with(ctx.config.compiler_check(), "string:")) { hash.hash_delimiter("cc_hash"); hash.hash(&ctx.config.compiler_check()[7]); @@ -1769,7 +1766,8 @@ hash_common_info(const Context& ctx, const util::Args& args, Hash& hash) // added to the hash to prevent false positive cache hits if the // mtime of the file changes. hash.hash_delimiter("-fbuild-session-file mtime"); - hash.hash(DirEntry(ctx.args_info.build_session_file).mtime().nsec()); + hash.hash( + util::nsec_tot(DirEntry(ctx.args_info.build_session_file).mtime())); } if (!ctx.config.extra_files_to_hash().empty()) { diff --git a/src/ccache/context.cpp b/src/ccache/context.cpp index 64ada878..ec82d17d 100644 --- a/src/ccache/context.cpp +++ b/src/ccache/context.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #ifdef HAVE_UNISTD_H @@ -46,7 +46,7 @@ Context::Context() #ifdef INODE_CACHE_SUPPORTED inode_cache(config), #endif - time_of_invocation(util::TimePoint::now()) + time_of_invocation(util::now()) { } diff --git a/src/ccache/context.hpp b/src/ccache/context.hpp index e8b688df..be9b8e9d 100644 --- a/src/ccache/context.hpp +++ b/src/ccache/context.hpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #ifdef INODE_CACHE_SUPPORTED # include diff --git a/src/ccache/core/cacheentry.cpp b/src/ccache/core/cacheentry.cpp index 224e0719..fff72625 100644 --- a/src/ccache/core/cacheentry.cpp +++ b/src/ccache/core/cacheentry.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include @@ -92,7 +92,7 @@ CacheEntry::Header::Header(const Config& config, compression_level(compression_level_from_config(config)), self_contained(entry_type != CacheEntryType::result || !core::result::Serializer::use_raw_files(config)), - creation_time(util::TimePoint::now().sec()), + creation_time(util::sec(util::now())), ccache_version(CCACHE_VERSION), namespace_(config.namespace_()), entry_size(0) diff --git a/src/ccache/core/manifest.cpp b/src/ccache/core/manifest.cpp index 2a3a0af5..12c7bf10 100644 --- a/src/ccache/core/manifest.cpp +++ b/src/ccache/core/manifest.cpp @@ -115,8 +115,10 @@ Manifest::read(nonstd::span data) reader.read_int(entry.index); reader.read_and_copy_bytes(entry.digest); reader.read_int(entry.fsize); - entry.mtime.set_nsec(reader.read_int()); - entry.ctime.set_nsec(reader.read_int()); + entry.mtime = + util::TimePoint(std::chrono::nanoseconds(reader.read_int())); + entry.ctime = + util::TimePoint(std::chrono::nanoseconds(reader.read_int())); } const auto result_count = reader.read_int(); @@ -282,8 +284,8 @@ Manifest::serialize(util::Bytes& output) writer.write_int(file_info.index); writer.write_bytes(file_info.digest); writer.write_int(file_info.fsize); - writer.write_int(file_info.mtime.nsec()); - writer.write_int(file_info.ctime.nsec()); + writer.write_int(util::nsec_tot(file_info.mtime)); + writer.write_int(util::nsec_tot(file_info.ctime)); } writer.write_int(static_cast(m_results.size())); @@ -467,16 +469,16 @@ Manifest::inspect(FILE* const stream) const } else { PRINT(stream, " Mtime: {}.{:09}\n", - m_file_infos[i].mtime.sec(), - m_file_infos[i].mtime.nsec_decimal_part()); + util::sec(m_file_infos[i].mtime), + util::nsec_part(m_file_infos[i].mtime)); } if (m_file_infos[i].ctime == util::TimePoint()) { PRINT_RAW(stream, " Ctime: -\n"); } else { PRINT(stream, " Ctime: {}.{:09}\n", - m_file_infos[i].ctime.sec(), - m_file_infos[i].ctime.nsec_decimal_part()); + util::sec(m_file_infos[i].ctime), + util::nsec_part(m_file_infos[i].ctime)); } } diff --git a/src/ccache/core/manifest.hpp b/src/ccache/core/manifest.hpp index b45b3919..10753c0e 100644 --- a/src/ccache/core/manifest.hpp +++ b/src/ccache/core/manifest.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2024 Joel Rosdahl and other contributors +// Copyright (C) 2009-2025 Joel Rosdahl and other contributors // // See doc/authors.adoc for a complete list of contributors. // @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include diff --git a/src/ccache/core/statistics.cpp b/src/ccache/core/statistics.cpp index 6324f070..2ea938d6 100644 --- a/src/ccache/core/statistics.cpp +++ b/src/ccache/core/statistics.cpp @@ -274,7 +274,7 @@ static_assert(std::size(k_statistics_fields) static std::string format_timestamp(const util::TimePoint& value) { - if (value.sec() == 0) { + if (util::sec(value) == 0) { return "never"; } else { const auto tm = util::localtime(value); @@ -404,7 +404,8 @@ Statistics::format_human_readable(const Config& config, table.add_row( {"Stats updated:", C(format_timestamp(last_updated)).colspan(4)}); if (verbosity > 1) { - const util::TimePoint last_zeroed(S(stats_zeroed_timestamp)); + const util::TimePoint last_zeroed( + std::chrono::seconds(S(stats_zeroed_timestamp))); table.add_row( {"Stats zeroed:", C(format_timestamp(last_zeroed)).colspan(4)}); } @@ -545,7 +546,7 @@ Statistics::prepare_statistics_entries( result.emplace_back("max_cache_size_kibibyte", config.max_size() / 1024); result.emplace_back("max_files_in_cache", config.max_files()); - result.emplace_back("stats_updated_timestamp", last_updated.sec()); + result.emplace_back("stats_updated_timestamp", util::sec(last_updated)); std::sort(result.begin(), result.end()); return result; diff --git a/src/ccache/core/statistics.hpp b/src/ccache/core/statistics.hpp index 05a7fd56..c82b2e06 100644 --- a/src/ccache/core/statistics.hpp +++ b/src/ccache/core/statistics.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2024 Joel Rosdahl and other contributors +// Copyright (C) 2020-2025 Joel Rosdahl and other contributors // // See doc/authors.adoc for a complete list of contributors. // @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include diff --git a/src/ccache/inodecache.cpp b/src/ccache/inodecache.cpp index 29d67e64..82452c7d 100644 --- a/src/ccache/inodecache.cpp +++ b/src/ccache/inodecache.cpp @@ -54,6 +54,8 @@ namespace fs = util::filesystem; +using namespace std::literals::chrono_literals; + // The inode cache resides on a file that is mapped into shared memory by // running processes. It is implemented as a two level structure, where the top // level is a hash table consisting of buckets. Each bucket contains entries @@ -309,7 +311,7 @@ InodeCache::hash_inode(const fs::path& path, } // See comment for InodeCache::InodeCache why this check is done. - auto now = util::TimePoint::now(); + auto now = util::now(); if (now - de.ctime() < m_min_age || now - de.mtime() < m_min_age) { LOG("Too new ctime or mtime of {}, not considering for inode cache", path); return false; @@ -323,10 +325,10 @@ InodeCache::hash_inode(const fs::path& path, key.st_mode = de.mode(); // Note: Manually copying sec and nsec of mtime and ctime to prevent copying // the padding bytes. - auto mtime = de.mtime().to_timespec(); + auto mtime = util::to_timespec(de.mtime()); key.st_mtim.tv_sec = mtime.tv_sec; key.st_mtim.tv_nsec = mtime.tv_nsec; - auto ctime = de.ctime().to_timespec(); + auto ctime = util::to_timespec(de.ctime()); key.st_ctim.tv_sec = ctime.tv_sec; key.st_ctim.tv_nsec = ctime.tv_nsec; key.st_size = de.size(); @@ -505,12 +507,11 @@ InodeCache::initialize() return false; } -InodeCache::InodeCache(const Config& config, util::Duration min_age) +InodeCache::InodeCache(const Config& config, std::chrono::nanoseconds min_age) : m_config(config), // CCACHE_DISABLE_INODE_CACHE_MIN_AGE is only for testing purposes; see // test/suites/inode_cache.bash. - m_min_age(getenv("CCACHE_DISABLE_INODE_CACHE_MIN_AGE") ? util::Duration(0) - : min_age), + m_min_age(getenv("CCACHE_DISABLE_INODE_CACHE_MIN_AGE") ? 0ns : min_age), m_self_pid(getpid()) { } diff --git a/src/ccache/inodecache.hpp b/src/ccache/inodecache.hpp index 79efe78f..21e3431a 100644 --- a/src/ccache/inodecache.hpp +++ b/src/ccache/inodecache.hpp @@ -20,10 +20,8 @@ #include #include -#include #include #include -#include #include @@ -71,7 +69,8 @@ public: // timestamp was updated more than `min_age` ago. The default value is a // conservative 2 seconds since not all file systems have subsecond // resolution. - InodeCache(const Config& config, util::Duration min_age = util::Duration(2)); + InodeCache(const Config& config, + std::chrono::nanoseconds min_age = std::chrono::seconds(2)); ~InodeCache(); // Return whether it's possible to use the inode cache on the filesystem @@ -139,7 +138,7 @@ private: bool initialize(); const Config& m_config; - util::Duration m_min_age; + std::chrono::nanoseconds m_min_age; util::Fd m_fd; struct SharedRegion* m_sr = nullptr; bool m_failed = false; diff --git a/src/ccache/storage/local/localstorage.cpp b/src/ccache/storage/local/localstorage.cpp index fcdeb3cc..09dba095 100644 --- a/src/ccache/storage/local/localstorage.cpp +++ b/src/ccache/storage/local/localstorage.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -42,6 +41,7 @@ #include #include #include +#include #include #ifdef INODE_CACHE_SUPPORTED @@ -85,6 +85,8 @@ namespace fs = util::filesystem; +using namespace std::literals::chrono_literals; + using core::AtomicFile; using core::Statistic; using core::StatisticsCounters; @@ -94,7 +96,7 @@ namespace storage::local { // How often (in seconds) to scan $CCACHE_DIR/tmp for left-over temporary // files. -const util::Duration k_tempdir_cleanup_interval(2 * 24 * 60 * 60); // 2 days +const auto k_tempdir_cleanup_interval = 2 * 24 * 60 * 60s; // C++20: 2d // Maximum files per cache directory. This constant is somewhat arbitrarily // chosen to be large enough to avoid unnecessary cache levels but small enough @@ -329,7 +331,7 @@ clean_dir( uint64_t cache_size = 0; uint64_t files_in_cache = 0; - auto current_time = util::TimePoint::now(); + auto current_time = util::now(); std::unordered_map /*associated_raw_files*/> raw_files_map; @@ -344,7 +346,7 @@ clean_dir( } // Delete any tmp files older than 1 hour right away. - if (file.mtime() + util::Duration(3600) < current_time + if (file.mtime() + 1h < current_time && util::TemporaryFile::is_tmp_file(file.path())) { std::ignore = util::remove(file.path()); continue; @@ -383,7 +385,7 @@ clean_dir( if ((max_size == 0 || cache_size <= max_size) && (max_files == 0 || files_in_cache <= max_files) && (!max_age - || file.mtime() > (current_time - util::Duration(*max_age))) + || file.mtime() > (current_time - std::chrono::seconds(*max_age))) && (!namespace_ || max_age)) { break; } @@ -746,7 +748,7 @@ LocalStorage::increment_statistics(const StatisticsCounters& statistics) void LocalStorage::zero_all_statistics() { - const auto now = util::TimePoint::now(); + const auto now = util::now(); const auto zeroable_fields = core::Statistics::get_zeroable_fields(); for_each_level_1_and_2_stats_file( @@ -755,7 +757,7 @@ LocalStorage::zero_all_statistics() for (const auto statistic : zeroable_fields) { cs.set(statistic, 0); } - cs.set(Statistic::stats_zeroed_timestamp, now.sec()); + cs.set(Statistic::stats_zeroed_timestamp, util::sec(now)); }); }); } @@ -1451,7 +1453,7 @@ LocalStorage::acquire_all_level_2_content_locks( void LocalStorage::clean_internal_tempdir() { - const auto now = util::TimePoint::now(); + const auto now = util::now(); const auto cleaned_stamp = FMT("{}/.cleaned", m_config.temporary_dir()); DirEntry cleaned_dir_entry(cleaned_stamp); if (cleaned_dir_entry.is_regular_file() diff --git a/src/ccache/storage/local/localstorage.hpp b/src/ccache/storage/local/localstorage.hpp index 6b31d93b..5ce7c793 100644 --- a/src/ccache/storage/local/localstorage.hpp +++ b/src/ccache/storage/local/localstorage.hpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include diff --git a/src/ccache/util/CMakeLists.txt b/src/ccache/util/CMakeLists.txt index b06df0b6..f4a03656 100644 --- a/src/ccache/util/CMakeLists.txt +++ b/src/ccache/util/CMakeLists.txt @@ -23,7 +23,6 @@ set( texttable.cpp threadpool.cpp time.cpp - timepoint.cpp tokenizer.cpp umaskscope.cpp zstd.cpp diff --git a/src/ccache/util/direntry.hpp b/src/ccache/util/direntry.hpp index 9b4f4ed5..270cc747 100644 --- a/src/ccache/util/direntry.hpp +++ b/src/ccache/util/direntry.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019-2024 Joel Rosdahl and other contributors +// Copyright (C) 2019-2025 Joel Rosdahl and other contributors // // See doc/authors.adoc for a complete list of contributors. // @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include @@ -212,13 +212,14 @@ inline util::TimePoint DirEntry::atime() const { #if defined(_WIN32) || defined(HAVE_STRUCT_STAT_ST_ATIM) - return util::TimePoint(do_stat().st_atim); + return util::timepoint_from_timespec(do_stat().st_atim); #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC) - return util::TimePoint(do_stat().st_atimespec); + return util::timepoint_from_timespec(do_stat().st_atimespec); #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC) - return util::TimePoint(do_stat().st_atime, do_stat().st_atimensec); + return util::timepoint_from_sec_nsec(do_stat().st_atime, + do_stat().st_atimensec); #else - return util::TimePoint(do_stat().st_atime, 0); + return util::timepoint_from_sec_nsec(do_stat().st_atime, 0); #endif } @@ -226,13 +227,14 @@ inline util::TimePoint DirEntry::ctime() const { #if defined(_WIN32) || defined(HAVE_STRUCT_STAT_ST_CTIM) - return util::TimePoint(do_stat().st_ctim); + return util::timepoint_from_timespec(do_stat().st_ctim); #elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC) - return util::TimePoint(do_stat().st_ctimespec); + return util::timepoint_from_timespec(do_stat().st_ctimespec); #elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC) - return util::TimePoint(do_stat().st_ctime, do_stat().st_ctimensec); + return util::timepoint_from_sec_nsec(do_stat().st_ctime, + do_stat().st_ctimensec); #else - return util::TimePoint(do_stat().st_ctime, 0); + return util::timepoint_from_sec_nsec(do_stat().st_ctime, 0); #endif } @@ -240,13 +242,14 @@ inline util::TimePoint DirEntry::mtime() const { #if defined(_WIN32) || defined(HAVE_STRUCT_STAT_ST_MTIM) - return util::TimePoint(do_stat().st_mtim); + return util::timepoint_from_timespec(do_stat().st_mtim); #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC) - return util::TimePoint(do_stat().st_mtimespec); + return util::timepoint_from_timespec(do_stat().st_mtimespec); #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - return util::TimePoint(do_stat().st_mtime, do_stat().st_mtimensec); + return util::timepoint_from_sec_nsec(do_stat().st_mtime, + do_stat().st_mtimensec); #else - return util::TimePoint(do_stat().st_mtime, 0); + return util::timepoint_from_sec_nsec(do_stat().st_mtime, 0); #endif } diff --git a/src/ccache/util/duration.hpp b/src/ccache/util/duration.hpp deleted file mode 100644 index 33590dfd..00000000 --- a/src/ccache/util/duration.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (C) 2022-2023 Joel Rosdahl and other contributors -// -// See doc/authors.adoc for a complete list of contributors. -// -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU 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 General Public License for -// more details. -// -// You should have received a copy of the GNU General Public License along with -// this program; if not, write to the Free Software Foundation, Inc., 51 -// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -#pragma once - -#include - -namespace util { - -class Duration -{ -public: - explicit Duration(int64_t sec = 0, int64_t nsec = 0); - - bool operator==(const Duration& other) const; - bool operator!=(const Duration& other) const; - bool operator<(const Duration& other) const; - bool operator>(const Duration& other) const; - bool operator<=(const Duration& other) const; - bool operator>=(const Duration& other) const; - - Duration operator+(const Duration& other) const; - Duration operator-(const Duration& other) const; - Duration operator*(double factor) const; - Duration operator/(double factor) const; - - Duration operator-() const; - - int64_t sec() const; - int64_t nsec() const; - int32_t nsec_decimal_part() const; - -private: - int64_t m_ns = 0; -}; - -inline Duration::Duration(int64_t sec, int64_t nsec) - : m_ns(1'000'000'000 * sec + nsec) -{ -} - -inline bool -Duration::operator==(const Duration& other) const -{ - return m_ns == other.m_ns; -} - -inline bool -Duration::operator!=(const Duration& other) const -{ - return m_ns != other.m_ns; -} - -inline bool -Duration::operator<(const Duration& other) const -{ - return m_ns < other.m_ns; -} - -inline bool -Duration::operator>(const Duration& other) const -{ - return m_ns > other.m_ns; -} - -inline bool -Duration::operator<=(const Duration& other) const -{ - return m_ns <= other.m_ns; -} - -inline bool -Duration::operator>=(const Duration& other) const -{ - return m_ns >= other.m_ns; -} - -inline Duration -Duration::operator+(const Duration& other) const -{ - return Duration(0, m_ns + other.m_ns); -} - -inline Duration -Duration::operator-(const Duration& other) const -{ - return Duration(0, m_ns - other.m_ns); -} - -inline Duration -Duration::operator*(double factor) const -{ - return Duration(0, static_cast(factor * static_cast(m_ns))); -} - -inline Duration -Duration::operator/(double factor) const -{ - return Duration(0, static_cast(static_cast(m_ns) / factor)); -} - -inline int64_t -Duration::sec() const -{ - return m_ns / 1'000'000'000; -} - -inline int64_t -Duration::nsec() const -{ - return m_ns; -} - -inline int32_t -Duration::nsec_decimal_part() const -{ - return static_cast(m_ns % 1'000'000'000); -} - -} // namespace util diff --git a/src/ccache/util/file.cpp b/src/ccache/util/file.cpp index 686a7028..4631eb33 100644 --- a/src/ccache/util/file.cpp +++ b/src/ccache/util/file.cpp @@ -540,26 +540,26 @@ set_timestamps(const fs::path& path, #ifdef HAVE_UTIMENSAT timespec atime_mtime[2]; if (mtime) { - atime_mtime[0] = (atime ? *atime : *mtime).to_timespec(); - atime_mtime[1] = mtime->to_timespec(); + atime_mtime[0] = util::to_timespec(atime ? *atime : *mtime); + atime_mtime[1] = util::to_timespec(*mtime); } utimensat( AT_FDCWD, util::pstr(path).c_str(), mtime ? atime_mtime : nullptr, 0); #elif defined(HAVE_UTIMES) timeval atime_mtime[2]; if (mtime) { - atime_mtime[0].tv_sec = atime ? atime->sec() : mtime->sec(); + atime_mtime[0].tv_sec = atime ? util::sec(*atime) : util::sec(*mtime); atime_mtime[0].tv_usec = (atime ? atime->nsec_decimal_part() : mtime->nsec_decimal_part()) / 1000; - atime_mtime[1].tv_sec = mtime->sec(); + atime_mtime[1].tv_sec = util::sec(*mtime); atime_mtime[1].tv_usec = mtime->nsec_decimal_part() / 1000; } utimes(util::pstr(path).c_str(), mtime ? atime_mtime : nullptr); #else utimbuf atime_mtime; if (mtime) { - atime_mtime.actime = atime ? atime->sec() : mtime->sec(); - atime_mtime.modtime = mtime->sec(); + atime_mtime.actime = atime ? util::sec(*atime) : util::sec(*mtime); + atime_mtime.modtime = util::sec(*mtime); utime(util::pstr(path).c_str(), &atime_mtime); } else { utime(util::pstr(path).c_str(), nullptr); diff --git a/src/ccache/util/file.hpp b/src/ccache/util/file.hpp index 783df5e9..107420df 100644 --- a/src/ccache/util/file.hpp +++ b/src/ccache/util/file.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2024 Joel Rosdahl and other contributors +// Copyright (C) 2021-2025 Joel Rosdahl and other contributors // // See doc/authors.adoc for a complete list of contributors. // @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include diff --git a/src/ccache/util/lockfile.cpp b/src/ccache/util/lockfile.cpp index aa8f84b7..3c91309f 100644 --- a/src/ccache/util/lockfile.cpp +++ b/src/ccache/util/lockfile.cpp @@ -41,14 +41,16 @@ #include #include +using namespace std::literals::chrono_literals; + +namespace fs = util::filesystem; + const uint32_t k_min_sleep_time_ms = 10; const uint32_t k_max_sleep_time_ms = 50; #ifndef _WIN32 -const util::Duration k_staleness_limit(2); +const auto k_staleness_limit = 2s; #endif -namespace fs = util::filesystem; - namespace { class RandomNumberGenerator @@ -230,7 +232,7 @@ LockFile::do_acquire(const bool blocking) TimePoint last_seen_activity = [this] { const auto last_lock_update = get_last_lock_update(); - return last_lock_update ? *last_lock_update : TimePoint::now(); + return last_lock_update ? *last_lock_update : util::now(); }(); std::string initial_content; @@ -238,9 +240,9 @@ LockFile::do_acquire(const bool blocking) k_max_sleep_time_ms); while (true) { - const auto now = TimePoint::now(); + const auto now = util::now(); const auto my_content = - FMT("{}-{}.{}", content_prefix, now.sec(), now.nsec_decimal_part()); + FMT("{}-{}.{}", content_prefix, util::sec(now), util::nsec_part(now)); # ifdef __CYGWIN__ // Cygwin/MSYS2 does not support allow a symlink to have a nonexistent // target, so use plain files instead. @@ -326,19 +328,19 @@ LockFile::do_acquire(const bool blocking) last_seen_activity = *last_lock_update; } - const Duration inactive_duration = TimePoint::now() - last_seen_activity; + const auto inactive_duration = util::now() - last_seen_activity; if (inactive_duration < k_staleness_limit) { LOG("Lock {} held by another process active {}.{:03} seconds ago", m_lock_file, - inactive_duration.sec(), - inactive_duration.nsec_decimal_part() / 1'000'000); + util::sec(inactive_duration), + util::nsec_part(inactive_duration) / 1'000'000); } else if (content == initial_content) { // The lock seems to be stale -- break it and try again. LOG("Breaking {} since it has been inactive for {}.{:03} seconds", m_lock_file, - inactive_duration.sec(), - inactive_duration.nsec_decimal_part() / 1'000'000); + util::sec(inactive_duration), + util::nsec_part(inactive_duration) / 1'000'000); if (auto r = fs::remove(m_alive_file); !r && r.error() != std::errc::no_such_file_or_directory) { return false; diff --git a/src/ccache/util/lockfile.hpp b/src/ccache/util/lockfile.hpp index 169fffe1..ef472c36 100644 --- a/src/ccache/util/lockfile.hpp +++ b/src/ccache/util/lockfile.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2024 Joel Rosdahl and other contributors +// Copyright (C) 2020-2025 Joel Rosdahl and other contributors // // See doc/authors.adoc for a complete list of contributors. // @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include diff --git a/src/ccache/util/logging.cpp b/src/ccache/util/logging.cpp index 5d1d3ae9..ec7a6440 100644 --- a/src/ccache/util/logging.cpp +++ b/src/ccache/util/logging.cpp @@ -82,12 +82,12 @@ do_log(std::string_view message, bool bulk) static char prefix[200]; if (!bulk || prefix[0] == '\0') { - const auto now = util::TimePoint::now(); + const auto now = util::now(); (void)snprintf(prefix, sizeof(prefix), "[%s.%06u %-5d] ", util::format_iso8601_timestamp(now).c_str(), - static_cast(now.nsec_decimal_part() / 1000), + static_cast(util::nsec_part(now) / 1000), static_cast(getpid())); } diff --git a/src/ccache/util/string.cpp b/src/ccache/util/string.cpp index c3729701..b82d6995 100644 --- a/src/ccache/util/string.cpp +++ b/src/ccache/util/string.cpp @@ -203,18 +203,15 @@ format_human_readable_size(uint64_t size, SizeUnitPrefixType prefix_type) std::string format_iso8601_timestamp(const TimePoint& time, TimeZone time_zone) { - char timestamp[100]; const auto tm = (time_zone == TimeZone::local ? util::localtime : util::gmtime)(time); if (tm) { + char timestamp[100]; (void)strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &*tm); + return timestamp; } else { - (void)snprintf(timestamp, - sizeof(timestamp), - "%llu", - static_cast(time.sec())); + return std::to_string(util::sec(time)); } - return timestamp; } std::string diff --git a/src/ccache/util/string.hpp b/src/ccache/util/string.hpp index dff3571f..13d7fd40 100644 --- a/src/ccache/util/string.hpp +++ b/src/ccache/util/string.hpp @@ -19,7 +19,7 @@ #pragma once #include -#include +#include #include #include @@ -27,6 +27,7 @@ #include // for mode_t +#include #include #include #include diff --git a/src/ccache/util/time.cpp b/src/ccache/util/time.cpp index 8630d267..30591eda 100644 --- a/src/ccache/util/time.cpp +++ b/src/ccache/util/time.cpp @@ -23,7 +23,7 @@ namespace util { std::optional gmtime(std::optional time) { - time_t timestamp = time ? time->sec() : TimePoint::now().sec(); + time_t timestamp = time ? sec(*time) : sec(now()); #ifdef HAVE_GMTIME_R struct tm result; if (gmtime_r(×tamp, &result)) { @@ -41,7 +41,7 @@ gmtime(std::optional time) std::optional localtime(std::optional time) { - time_t timestamp = time ? time->sec() : TimePoint::now().sec(); + time_t timestamp = time ? sec(*time) : sec(now()); #ifdef HAVE_LOCALTIME_R struct tm result; if (localtime_r(×tamp, &result)) { diff --git a/src/ccache/util/time.hpp b/src/ccache/util/time.hpp index 16d90af6..458f646d 100644 --- a/src/ccache/util/time.hpp +++ b/src/ccache/util/time.hpp @@ -18,13 +18,17 @@ #pragma once -#include - +#include #include #include namespace util { +// --- Interface --- + +using TimePoint = + std::chrono::time_point; + // Thread-safe version of `gmtime(3)`. If `time` is not specified the current // time of day is used. std::optional gmtime(std::optional time = {}); @@ -33,4 +37,93 @@ std::optional gmtime(std::optional time = {}); // time of day is used. std::optional localtime(std::optional time = {}); +TimePoint now(); + +template +int32_t nsec_part(std::chrono::duration d); + +int32_t nsec_part(TimePoint tp); + +template +int64_t nsec_tot(std::chrono::duration d); + +int64_t nsec_tot(TimePoint tp); + +template +int64_t sec(std::chrono::duration d); + +int64_t sec(TimePoint tp); + +TimePoint timepoint_from_sec_nsec(int64_t sec, int64_t nsec); + +TimePoint timepoint_from_timespec(const timespec& ts); + +timespec to_timespec(TimePoint tp); + +// --- Inline implementations --- + +inline TimePoint +timepoint_from_sec_nsec(int64_t sec, int64_t nsec) +{ + return TimePoint(std::chrono::seconds(sec) + std::chrono::nanoseconds(nsec)); +} + +inline TimePoint +timepoint_from_timespec(const timespec& ts) +{ + return TimePoint(std::chrono::seconds(ts.tv_sec) + + std::chrono::nanoseconds(ts.tv_nsec)); +} + +inline TimePoint +now() +{ + return std::chrono::system_clock::now(); +} + +template +inline int64_t +nsec_tot(std::chrono::duration d) +{ + return std::chrono::duration_cast(d).count(); +} + +inline int64_t +nsec_tot(TimePoint tp) +{ + return tp.time_since_epoch().count(); +} + +template +inline int64_t +sec(std::chrono::duration d) +{ + return nsec_tot(d) / 1'000'000'000; +} + +inline int64_t +sec(TimePoint tp) +{ + return nsec_tot(tp) / 1'000'000'000; +} + +template +inline int32_t +nsec_part(std::chrono::duration d) +{ + return nsec_tot(d) % 1'000'000'000; +} + +inline int32_t +nsec_part(TimePoint tp) +{ + return nsec_tot(tp) % 1'000'000'000; +} + +inline timespec +to_timespec(TimePoint tp) +{ + return {static_cast(util::sec(tp)), util::nsec_part(tp)}; +} + } // namespace util diff --git a/src/ccache/util/timepoint.cpp b/src/ccache/util/timepoint.cpp deleted file mode 100644 index d22432c6..00000000 --- a/src/ccache/util/timepoint.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2022-2024 Joel Rosdahl and other contributors -// -// See doc/authors.adoc for a complete list of contributors. -// -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU 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 General Public License for -// more details. -// -// You should have received a copy of the GNU General Public License along with -// this program; if not, write to the Free Software Foundation, Inc., 51 -// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -#include "timepoint.hpp" - -#include - -namespace util { - -TimePoint -TimePoint::now() -{ - return TimePoint(0, - std::chrono::time_point_cast( - std::chrono::system_clock::now()) - .time_since_epoch() - .count()); -} - -} // namespace util diff --git a/src/ccache/util/timepoint.hpp b/src/ccache/util/timepoint.hpp deleted file mode 100644 index 65e0c36a..00000000 --- a/src/ccache/util/timepoint.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) 2022-2024 Joel Rosdahl and other contributors -// -// See doc/authors.adoc for a complete list of contributors. -// -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU 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 General Public License for -// more details. -// -// You should have received a copy of the GNU General Public License along with -// this program; if not, write to the Free Software Foundation, Inc., 51 -// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -#pragma once - -#include - -#include -#include - -namespace util { - -class TimePoint -{ -public: - explicit TimePoint(int64_t sec = 0, int64_t nsec = 0); - TimePoint(const TimePoint& other); - explicit TimePoint(const timespec& timespec); - - TimePoint& operator=(const TimePoint& other); - - static TimePoint now(); - - timespec to_timespec() const; - - int64_t sec() const; - int64_t nsec() const; - int32_t nsec_decimal_part() const; - - void set_sec(int64_t sec, uint32_t nsec = 0); - void set_nsec(int64_t nsec); - - bool operator==(const TimePoint& other) const; - bool operator!=(const TimePoint& other) const; - bool operator<(const TimePoint& other) const; - bool operator>(const TimePoint& other) const; - bool operator<=(const TimePoint& other) const; - bool operator>=(const TimePoint& other) const; - - TimePoint operator+(const Duration& duration) const; - TimePoint operator-(const Duration& duration) const; - - Duration operator-(const TimePoint& other) const; - -private: - int64_t m_ns = 0; -}; - -inline TimePoint::TimePoint(int64_t sec, int64_t nsec) - : m_ns(1'000'000'000 * sec + nsec) -{ -} - -inline TimePoint::TimePoint(const TimePoint& other) - : m_ns(other.m_ns) -{ -} - -inline TimePoint::TimePoint(const timespec& timespec) - : TimePoint(timespec.tv_sec, timespec.tv_nsec) -{ -} - -inline TimePoint& -TimePoint::operator=(const TimePoint& other) -{ - m_ns = other.m_ns; - return *this; -} - -inline timespec -TimePoint::to_timespec() const -{ - return {static_cast(sec()), nsec_decimal_part()}; -} - -inline int64_t -TimePoint::sec() const -{ - return m_ns / 1'000'000'000; -} - -inline int64_t -TimePoint::nsec() const -{ - return m_ns; -} - -inline int32_t -TimePoint::nsec_decimal_part() const -{ - return static_cast(m_ns % 1'000'000'000); -} - -inline void -TimePoint::set_sec(int64_t sec, uint32_t nsec) -{ - m_ns = 1'000'000'000 * sec + nsec; -} - -inline void -TimePoint::set_nsec(int64_t nsec) -{ - m_ns = nsec; -} - -inline bool -TimePoint::operator==(const TimePoint& other) const -{ - return m_ns == other.m_ns; -} - -inline bool -TimePoint::operator!=(const TimePoint& other) const -{ - return m_ns != other.m_ns; -} - -inline bool -TimePoint::operator<(const TimePoint& other) const -{ - return m_ns < other.m_ns; -} - -inline bool -TimePoint::operator>(const TimePoint& other) const -{ - return m_ns > other.m_ns; -} - -inline bool -TimePoint::operator<=(const TimePoint& other) const -{ - return m_ns <= other.m_ns; -} - -inline bool -TimePoint::operator>=(const TimePoint& other) const -{ - return m_ns >= other.m_ns; -} - -inline TimePoint -TimePoint::operator+(const Duration& duration) const -{ - return TimePoint(0, nsec() + duration.nsec()); -} - -inline TimePoint -TimePoint::operator-(const Duration& duration) const -{ - return TimePoint(0, nsec() - duration.nsec()); -} - -inline Duration -TimePoint::operator-(const TimePoint& other) const -{ - return Duration(0, nsec() - other.nsec()); -} - -} // namespace util diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 369ec9c5..f333b3d9 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -23,7 +23,6 @@ set( test_util_clang.cpp test_util_conversion.cpp test_util_direntry.cpp - test_util_duration.cpp test_util_environment.cpp test_util_exec.cpp test_util_expected.cpp @@ -32,7 +31,6 @@ set( test_util_path.cpp test_util_string.cpp test_util_texttable.cpp - test_util_timepoint.cpp test_util_tokenizer.cpp test_util_xxh3_128.cpp test_util_xxh3_64.cpp diff --git a/unittest/test_inodecache.cpp b/unittest/test_inodecache.cpp index f0a6cedb..7e60ca92 100644 --- a/unittest/test_inodecache.cpp +++ b/unittest/test_inodecache.cpp @@ -34,8 +34,12 @@ #include #include +#include + namespace fs = util::filesystem; +using namespace std::literals::chrono_literals; + using TestUtil::TestContext; namespace { @@ -84,7 +88,7 @@ TEST_CASE("Test disabled") Config config; init(config); config.set_inode_cache(false); - InodeCache inode_cache(config, util::Duration(0)); + InodeCache inode_cache(config, 0ns); CHECK(!inode_cache.get("a", InodeCache::ContentType::checked_for_temporal_macros)); @@ -104,7 +108,7 @@ TEST_CASE("Test lookup nonexistent") Config config; init(config); - InodeCache inode_cache(config, util::Duration(0)); + InodeCache inode_cache(config, 0ns); REQUIRE(util::write_file("a", "")); CHECK(!inode_cache.get("a", @@ -121,7 +125,7 @@ TEST_CASE("Test put and lookup") Config config; init(config); - InodeCache inode_cache(config, util::Duration(0)); + InodeCache inode_cache(config, 0ns); REQUIRE(util::write_file("a", "a text")); HashSourceCodeResult result; @@ -169,7 +173,7 @@ TEST_CASE("Drop file") Config config; init(config); - InodeCache inode_cache(config, util::Duration(0)); + InodeCache inode_cache(config, 0ns); inode_cache.get("a", InodeCache::ContentType::raw); CHECK(util::DirEntry(inode_cache.get_path())); @@ -185,7 +189,7 @@ TEST_CASE("Test content type") Config config; init(config); - InodeCache inode_cache(config, util::Duration(0)); + InodeCache inode_cache(config, 0ns); REQUIRE(util::write_file("a", "a text")); auto binary_digest = Hash().hash("binary").digest(); auto code_digest = Hash().hash("code").digest(); diff --git a/unittest/test_util_direntry.cpp b/unittest/test_util_direntry.cpp index 411300fe..5af7ee12 100644 --- a/unittest/test_util_direntry.cpp +++ b/unittest/test_util_direntry.cpp @@ -162,10 +162,10 @@ TEST_CASE("Default constructor") CHECK(entry.device() == 0); CHECK(entry.inode() == 0); CHECK(entry.mode() == 0); - CHECK(entry.ctime().sec() == 0); - CHECK(entry.ctime().nsec() == 0); - CHECK(entry.mtime().sec() == 0); - CHECK(entry.mtime().nsec() == 0); + CHECK(util::sec(entry.ctime()) == 0); + CHECK(util::nsec_part(entry.ctime()) == 0); + CHECK(util::sec(entry.mtime()) == 0); + CHECK(util::nsec_part(entry.mtime()) == 0); CHECK(entry.size() == 0); CHECK(entry.size_on_disk() == 0); CHECK(!entry.is_directory()); @@ -188,10 +188,10 @@ TEST_CASE("Construction for missing entry") CHECK(entry.device() == 0); CHECK(entry.inode() == 0); CHECK(entry.mode() == 0); - CHECK(entry.ctime().sec() == 0); - CHECK(entry.ctime().nsec() == 0); - CHECK(entry.mtime().sec() == 0); - CHECK(entry.mtime().nsec() == 0); + CHECK(util::sec(entry.ctime()) == 0); + CHECK(util::nsec_part(entry.ctime()) == 0); + CHECK(util::sec(entry.mtime()) == 0); + CHECK(util::nsec_part(entry.mtime()) == 0); CHECK(entry.size() == 0); CHECK(entry.size_on_disk() == 0); CHECK(!entry.is_directory()); @@ -294,10 +294,10 @@ TEST_CASE("Return values when file exists") struct timespec last_write_time = win32_filetime_to_timespec(info.ftLastWriteTime); - CHECK(de.ctime().sec() == creation_time.tv_sec); - CHECK(de.ctime().nsec_decimal_part() == creation_time.tv_nsec); - CHECK(de.mtime().sec() == last_write_time.tv_sec); - CHECK(de.mtime().nsec_decimal_part() == last_write_time.tv_nsec); + CHECK(util::sec(de.ctime()) == creation_time.tv_sec); + CHECK(util::nsec_part(de.ctime()) == creation_time.tv_nsec); + CHECK(util::sec(de.mtime()) == last_write_time.tv_sec); + CHECK(util::nsec_part(de.mtime()) == last_write_time.tv_nsec); CHECK(de.size_on_disk() == ((de.size() + 4095) & ~4095)); CHECK(de.file_attributes() == info.dwFileAttributes); @@ -313,25 +313,25 @@ TEST_CASE("Return values when file exists") CHECK(de.size_on_disk() == util::likely_size_on_disk(st.st_size)); # ifdef HAVE_STRUCT_STAT_ST_CTIM - CHECK(de.ctime().sec() == st.st_ctim.tv_sec); - CHECK(de.ctime().nsec_decimal_part() == st.st_ctim.tv_nsec); + CHECK(util::sec(de.ctime()) == st.st_ctim.tv_sec); + CHECK(util::nsec_part(de.ctime()) == st.st_ctim.tv_nsec); # elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC) - CHECK(de.ctime().sec() == st.st_ctimespec.tv_sec); - CHECK(de.ctime().nsec_decimal_part() == st.st_ctimespec.tv_nsec); + CHECK(util::sec(de.ctime()) == st.st_ctimespec.tv_sec); + CHECK(util::nsec_part(de.ctime()) == st.st_ctimespec.tv_nsec); # else - CHECK(de.ctime().sec() == st.st_ctime); - CHECK(de.ctime().nsec_decimal_part() == 0); + CHECK(util::sec(de.ctime()) == st.st_ctime); + CHECK(util::nsec_part(de.ctime()) == 0); # endif # ifdef HAVE_STRUCT_STAT_ST_MTIM - CHECK(de.mtime().sec() == st.st_mtim.tv_sec); - CHECK(de.mtime().nsec_decimal_part() == st.st_mtim.tv_nsec); + CHECK(util::sec(de.mtime()) == st.st_mtim.tv_sec); + CHECK(util::nsec_part(de.mtime()) == st.st_mtim.tv_nsec); # elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC) - CHECK(de.mtime().sec() == st.st_mtimespec.tv_sec); - CHECK(de.mtime().nsec_decimal_part() == st.st_mtimespec.tv_nsec); + CHECK(util::sec(de.mtime()) == st.st_mtimespec.tv_sec); + CHECK(util::nsec_part(de.mtime()) == st.st_mtimespec.tv_nsec); # else - CHECK(de.mtime().sec() == st.st_mtime); - CHECK(de.mtime().nsec_decimal_part() == 0); + CHECK(util::sec(de.mtime()) == st.st_mtime); + CHECK(util::nsec_part(de.mtime()) == 0); # endif #endif } diff --git a/unittest/test_util_duration.cpp b/unittest/test_util_duration.cpp deleted file mode 100644 index c420be15..00000000 --- a/unittest/test_util_duration.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (C) 2022-2024 Joel Rosdahl and other contributors -// -// See doc/authors.adoc for a complete list of contributors. -// -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU 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 General Public License for -// more details. -// -// You should have received a copy of the GNU General Public License along with -// this program; if not, write to the Free Software Foundation, Inc., 51 -// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -#include - -#include - -TEST_SUITE_BEGIN("util::Duration"); - -using util::Duration; - -TEST_CASE("Basics") -{ - Duration d0(4711, 2042); - - CHECK(d0.sec() == 4711); - CHECK(d0.nsec() == 4711000002042); - CHECK(d0.nsec_decimal_part() == 2042); -} - -TEST_CASE("Comparison operators") -{ - Duration d0(1000, 0); - Duration d1(1000, 42); - Duration d2(1001, 0); - - SUBCASE("operator==") - { - CHECK(d0 == d0); - CHECK(!(d0 == d1)); - CHECK(!(d1 == d0)); - CHECK(!(d0 == d2)); - CHECK(!(d2 == d0)); - } - - SUBCASE("operator!=") - { - CHECK(!(d0 != d0)); - CHECK(d0 != d1); - CHECK(d1 != d0); - } - - SUBCASE("operator<") - { - CHECK(d0 < d1); - CHECK(d0 < d2); - CHECK(d1 < d2); - CHECK(!(d1 < d0)); - CHECK(!(d2 < d0)); - CHECK(!(d2 < d1)); - } - - SUBCASE("operator>") - { - CHECK(d2 > d1); - CHECK(d2 > d0); - CHECK(d1 > d0); - CHECK(!(d1 > d2)); - CHECK(!(d0 > d2)); - CHECK(!(d0 > d1)); - } - - SUBCASE("operator<=") - { - CHECK(d0 <= d0); - CHECK(d0 <= d1); - CHECK(d0 <= d2); - CHECK(!(d1 <= d0)); - CHECK(!(d2 <= d0)); - } - - SUBCASE("operator>=") - { - CHECK(d2 >= d1); - CHECK(d2 >= d0); - CHECK(d1 >= d0); - CHECK(!(d1 >= d2)); - CHECK(!(d0 >= d2)); - } -} - -TEST_CASE("Arithmetic operators") -{ - Duration d0(1, 2); - Duration d1(3, 9); - - SUBCASE("operator+") - { - Duration d = d0 + d1; - CHECK(d.sec() == 4); - CHECK(d.nsec_decimal_part() == 11); - } - - SUBCASE("operator-") - { - Duration d = d0 - d1; - CHECK(d.sec() == -2); - CHECK(d.nsec_decimal_part() == -7); - } - - SUBCASE("operator*") - { - Duration d = d1 * 4; - CHECK(d.sec() == 12); - CHECK(d.nsec_decimal_part() == 36); - } - - SUBCASE("operator/") - { - Duration d = d1 / 0.8; - CHECK(d.sec() == 3); - CHECK(d.nsec_decimal_part() == 750'000'011); - } -} - -TEST_SUITE_END(); diff --git a/unittest/test_util_lockfile.cpp b/unittest/test_util_lockfile.cpp index 8652c3a2..acc0a37a 100644 --- a/unittest/test_util_lockfile.cpp +++ b/unittest/test_util_lockfile.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -116,7 +117,7 @@ TEST_CASE("Break stale lock, blocking") TestContext test_context; REQUIRE(util::write_file("test.alive", "")); - const util::TimePoint long_time_ago(0, 0); + const util::TimePoint long_time_ago(0s); util::set_timestamps("test.alive", long_time_ago); CHECK(symlink("foo", "test.lock") == 0); @@ -131,7 +132,7 @@ TEST_CASE("Break stale lock, non-blocking") TestContext test_context; REQUIRE(util::write_file("test.alive", "")); - const util::TimePoint long_time_ago(0, 0); + const util::TimePoint long_time_ago(0s); util::set_timestamps("test.alive", long_time_ago); CHECK(symlink("foo", "test.lock") == 0); diff --git a/unittest/test_util_string.cpp b/unittest/test_util_string.cpp index 8a6138bc..2859ba34 100644 --- a/unittest/test_util_string.cpp +++ b/unittest/test_util_string.cpp @@ -20,9 +20,12 @@ #include +#include #include // https://github.com/doctest/doctest/issues/618 #include +using namespace std::literals::chrono_literals; + TEST_SUITE_BEGIN("util"); TEST_CASE("util::format_argv_as_win32_command_string") @@ -265,9 +268,9 @@ TEST_CASE("util::format_iso8601_timestamp") using util::TimePoint; using util::TimeZone; - CHECK(util::format_iso8601_timestamp(TimePoint(0), TimeZone::utc) + CHECK(util::format_iso8601_timestamp(TimePoint(0s), TimeZone::utc) == "1970-01-01T00:00:00"); - CHECK(util::format_iso8601_timestamp(TimePoint(1234567890), TimeZone::utc) + CHECK(util::format_iso8601_timestamp(TimePoint(1234567890s), TimeZone::utc) == "2009-02-13T23:31:30"); } diff --git a/unittest/test_util_timepoint.cpp b/unittest/test_util_timepoint.cpp deleted file mode 100644 index 44acb7bb..00000000 --- a/unittest/test_util_timepoint.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (C) 2022-2024 Joel Rosdahl and other contributors -// -// See doc/authors.adoc for a complete list of contributors. -// -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU 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 General Public License for -// more details. -// -// You should have received a copy of the GNU General Public License along with -// this program; if not, write to the Free Software Foundation, Inc., 51 -// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -#include - -#include - -TEST_SUITE_BEGIN("util::TimePoint"); - -using util::TimePoint; - -TEST_CASE("Basics") -{ - TimePoint t0(4711, 2042); - - CHECK(t0.sec() == 4711); - CHECK(t0.nsec() == 4711000002042); - CHECK(t0.nsec_decimal_part() == 2042); -} - -TEST_CASE("Conversions") -{ - TimePoint t0(4711, 2042); - - SUBCASE("to_timespec") - { - timespec ts = t0.to_timespec(); - CHECK(ts.tv_sec == 4711); - CHECK(ts.tv_nsec == 2042); - } -} - -TEST_CASE("Comparison operators") -{ - TimePoint t0(1000, 0); - TimePoint t1(1000, 42); - TimePoint t2(1001, 0); - - SUBCASE("operator==") - { - CHECK(t0 == t0); - CHECK(!(t0 == t1)); - CHECK(!(t1 == t0)); - CHECK(!(t0 == t2)); - CHECK(!(t2 == t0)); - } - - SUBCASE("operator!=") - { - CHECK(!(t0 != t0)); - CHECK(t0 != t1); - CHECK(t1 != t0); - } - - SUBCASE("operator<") - { - CHECK(t0 < t1); - CHECK(t0 < t2); - CHECK(t1 < t2); - CHECK(!(t1 < t0)); - CHECK(!(t2 < t0)); - CHECK(!(t2 < t1)); - } - - SUBCASE("operator>") - { - CHECK(t2 > t1); - CHECK(t2 > t0); - CHECK(t1 > t0); - CHECK(!(t1 > t2)); - CHECK(!(t0 > t2)); - CHECK(!(t0 > t1)); - } - - SUBCASE("operator<=") - { - CHECK(t0 <= t0); - CHECK(t0 <= t1); - CHECK(t0 <= t2); - CHECK(!(t1 <= t0)); - CHECK(!(t2 <= t0)); - } - - SUBCASE("operator>=") - { - CHECK(t2 >= t1); - CHECK(t2 >= t0); - CHECK(t1 >= t0); - CHECK(!(t1 >= t2)); - CHECK(!(t0 >= t2)); - } -} - -TEST_CASE("Operations with duration") -{ - TimePoint t0(1, 2); - TimePoint t1(3, 17); - - SUBCASE("operator-(TimePoint)") - { - CHECK(t1 - t0 == util::Duration(2, 15)); - CHECK(t0 - t1 == util::Duration(-2, -15)); - } - - SUBCASE("operator+(Duration)") - { - CHECK(t0 + util::Duration(4, 999999999) == util::TimePoint(6, 1)); - } - - SUBCASE("operator-(Duration))") - { - auto t = t0 - util::Duration(4, 999999999); - CHECK(t.sec() == -3); - CHECK(t.nsec_decimal_part() == -999999997); - } -} - -TEST_SUITE_END();