#include <ccache/util/conversion.hpp>
#include <ccache/util/defer.hpp>
#include <ccache/util/direntry.hpp>
-#include <ccache/util/duration.hpp>
#include <ccache/util/environment.hpp>
#include <ccache/util/exec.hpp>
#include <ccache/util/expected.hpp>
#include <ccache/util/string.hpp>
#include <ccache/util/temporaryfile.hpp>
#include <ccache/util/time.hpp>
-#include <ccache/util/timepoint.hpp>
#include <ccache/util/tokenizer.hpp>
#include <ccache/util/umaskscope.hpp>
#include <ccache/util/wincompat.hpp>
namespace fs = util::filesystem;
+using namespace std::literals::chrono_literals;
+
using core::Statistic;
using util::DirEntry;
// 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<long long unsigned int>(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);
}
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
// 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);
} 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]);
// 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()) {
#include <ccache/util/path.hpp>
#include <ccache/util/process.hpp>
#include <ccache/util/string.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <ccache/util/wincompat.hpp>
#ifdef HAVE_UNISTD_H
#ifdef INODE_CACHE_SUPPORTED
inode_cache(config),
#endif
- time_of_invocation(util::TimePoint::now())
+ time_of_invocation(util::now())
{
}
#include <ccache/util/bytes.hpp>
#include <ccache/util/filestream.hpp>
#include <ccache/util/noncopyable.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#ifdef INODE_CACHE_SUPPORTED
# include <ccache/inodecache.hpp>
#include <ccache/util/filesystem.hpp>
#include <ccache/util/format.hpp>
#include <ccache/util/logging.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <ccache/util/xxh3_128.hpp>
#include <ccache/util/zstd.hpp>
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)
reader.read_int(entry.index);
reader.read_and_copy_bytes(entry.digest);
reader.read_int(entry.fsize);
- entry.mtime.set_nsec(reader.read_int<int64_t>());
- entry.ctime.set_nsec(reader.read_int<int64_t>());
+ entry.mtime =
+ util::TimePoint(std::chrono::nanoseconds(reader.read_int<int64_t>()));
+ entry.ctime =
+ util::TimePoint(std::chrono::nanoseconds(reader.read_int<int64_t>()));
}
const auto result_count = reader.read_int<uint32_t>();
writer.write_int<uint32_t>(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<uint32_t>(m_results.size()));
} 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));
}
}
-// 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.
//
#include <ccache/core/serializer.hpp>
#include <ccache/hash.hpp>
#include <ccache/util/bytes.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <nonstd/span.hpp>
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);
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)});
}
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;
-// 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.
//
#include <ccache/core/statistic.hpp>
#include <ccache/core/statisticscounters.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <cstdint>
#include <string>
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
}
// 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;
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();
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())
{
}
#include <ccache/hash.hpp>
#include <ccache/hashutil.hpp>
-#include <ccache/util/duration.hpp>
#include <ccache/util/fd.hpp>
#include <ccache/util/memorymap.hpp>
-#include <ccache/util/timepoint.hpp>
#include <sys/types.h>
// 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
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;
#include <ccache/core/manifest.hpp>
#include <ccache/core/statistics.hpp>
#include <ccache/util/assertions.hpp>
-#include <ccache/util/duration.hpp>
#include <ccache/util/expected.hpp>
#include <ccache/util/file.hpp>
#include <ccache/util/filestream.hpp>
#include <ccache/util/temporaryfile.hpp>
#include <ccache/util/texttable.hpp>
#include <ccache/util/threadpool.hpp>
+#include <ccache/util/time.hpp>
#include <ccache/util/wincompat.hpp>
#ifdef INODE_CACHE_SUPPORTED
namespace fs = util::filesystem;
+using namespace std::literals::chrono_literals;
+
using core::AtomicFile;
using core::Statistic;
using core::StatisticsCounters;
// 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
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<std::string /*result_file*/,
std::vector<fs::path> /*associated_raw_files*/>
raw_files_map;
}
// 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;
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;
}
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(
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));
});
});
}
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()
#include <ccache/util/direntry.hpp>
#include <ccache/util/lockfile.hpp>
#include <ccache/util/longlivedlockfilemanager.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <nonstd/span.hpp>
texttable.cpp
threadpool.cpp
time.cpp
- timepoint.cpp
tokenizer.cpp
umaskscope.cpp
zstd.cpp
-// 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.
//
#pragma once
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <ccache/util/wincompat.hpp>
#include <sys/stat.h>
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
}
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
}
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
}
+++ /dev/null
-// 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 <cstdint>
-
-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<int64_t>(factor * static_cast<double>(m_ns)));
-}
-
-inline Duration
-Duration::operator/(double factor) const
-{
- return Duration(0, static_cast<int64_t>(static_cast<double>(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<int32_t>(m_ns % 1'000'000'000);
-}
-
-} // namespace util
#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);
-// 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.
//
#include <ccache/util/bytes.hpp>
#include <ccache/util/direntry.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <ccache/util/types.hpp>
#include <nonstd/span.hpp>
#include <random>
#include <sstream>
+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
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;
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.
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;
-// 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.
//
#include <ccache/util/longlivedlockfilemanager.hpp>
#include <ccache/util/noncopyable.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <filesystem>
#include <optional>
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<unsigned int>(now.nsec_decimal_part() / 1000),
+ static_cast<unsigned int>(util::nsec_part(now) / 1000),
static_cast<int>(getpid()));
}
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<long long unsigned int>(time.sec()));
+ return std::to_string(util::sec(time));
}
- return timestamp;
}
std::string
#pragma once
#include <ccache/util/conversion.hpp>
-#include <ccache/util/timepoint.hpp>
+#include <ccache/util/time.hpp>
#include <ccache/util/tokenizer.hpp>
#include <nonstd/span.hpp>
#include <sys/stat.h> // for mode_t
+#include <chrono>
#include <cstdint>
#include <cstring>
#include <filesystem>
std::optional<tm>
gmtime(std::optional<TimePoint> 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)) {
std::optional<tm>
localtime(std::optional<TimePoint> 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)) {
#pragma once
-#include <ccache/util/timepoint.hpp>
-
+#include <chrono>
#include <ctime>
#include <optional>
namespace util {
+// --- Interface ---
+
+using TimePoint =
+ std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>;
+
// Thread-safe version of `gmtime(3)`. If `time` is not specified the current
// time of day is used.
std::optional<tm> gmtime(std::optional<TimePoint> time = {});
// time of day is used.
std::optional<tm> localtime(std::optional<TimePoint> time = {});
+TimePoint now();
+
+template<typename Rep, typename Period>
+int32_t nsec_part(std::chrono::duration<Rep, Period> d);
+
+int32_t nsec_part(TimePoint tp);
+
+template<typename Rep, typename Period>
+int64_t nsec_tot(std::chrono::duration<Rep, Period> d);
+
+int64_t nsec_tot(TimePoint tp);
+
+template<typename Rep, typename Period>
+int64_t sec(std::chrono::duration<Rep, Period> 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<typename Rep, typename Period>
+inline int64_t
+nsec_tot(std::chrono::duration<Rep, Period> d)
+{
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(d).count();
+}
+
+inline int64_t
+nsec_tot(TimePoint tp)
+{
+ return tp.time_since_epoch().count();
+}
+
+template<typename Rep, typename Period>
+inline int64_t
+sec(std::chrono::duration<Rep, Period> d)
+{
+ return nsec_tot(d) / 1'000'000'000;
+}
+
+inline int64_t
+sec(TimePoint tp)
+{
+ return nsec_tot(tp) / 1'000'000'000;
+}
+
+template<typename Rep, typename Period>
+inline int32_t
+nsec_part(std::chrono::duration<Rep, Period> 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<time_t>(util::sec(tp)), util::nsec_part(tp)};
+}
+
} // namespace util
+++ /dev/null
-// 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 <chrono>
-
-namespace util {
-
-TimePoint
-TimePoint::now()
-{
- return TimePoint(0,
- std::chrono::time_point_cast<std::chrono::nanoseconds>(
- std::chrono::system_clock::now())
- .time_since_epoch()
- .count());
-}
-
-} // namespace util
+++ /dev/null
-// 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 <ccache/util/duration.hpp>
-
-#include <cstdint>
-#include <ctime>
-
-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<time_t>(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<int32_t>(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
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
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
#include <sys/stat.h>
#include <sys/types.h>
+#include <chrono>
+
namespace fs = util::filesystem;
+using namespace std::literals::chrono_literals;
+
using TestUtil::TestContext;
namespace {
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));
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",
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;
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()));
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();
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());
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());
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);
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
}
+++ /dev/null
-// 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 <ccache/util/duration.hpp>
-
-#include <doctest/doctest.h>
-
-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();
#include <ccache/util/direntry.hpp>
#include <ccache/util/file.hpp>
#include <ccache/util/lockfile.hpp>
+#include <ccache/util/time.hpp>
#include <ccache/util/wincompat.hpp>
#include <doctest/doctest.h>
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);
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);
#include <doctest/doctest.h>
+#include <chrono>
#include <ostream> // https://github.com/doctest/doctest/issues/618
#include <vector>
+using namespace std::literals::chrono_literals;
+
TEST_SUITE_BEGIN("util");
TEST_CASE("util::format_argv_as_win32_command_string")
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");
}
+++ /dev/null
-// 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 <ccache/util/timepoint.hpp>
-
-#include <doctest/doctest.h>
-
-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();