/* * Copyright 2016 The Cartographer Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System.Runtime.InteropServices; namespace CartographerSharp.Common.Time; /// /// Universal Time Scale clock for Cartographer. /// Represents durations and timestamps as 64-bit integers representing /// 100 nanosecond ticks since the Epoch (January 1, 1 at the start of day in UTC). /// public static partial class TimeUtils { /// /// UTS Epoch offset from Unix Epoch in seconds. /// public const long UtsEpochOffsetFromUnixEpochInSeconds = 719162L * 24L * 60L * 60L; /// /// Ticks per second in Universal Time Scale (100 nanoseconds = 10,000,000 ticks per second). /// public const long TicksPerSecond = 10_000_000L; /// /// Creates a Duration from seconds. /// public static TimeSpan FromSeconds(double seconds) { return TimeSpan.FromTicks((long)(seconds * TicksPerSecond)); } /// /// Creates a Duration from milliseconds. /// public static TimeSpan FromMilliseconds(long milliseconds) { // Convert milliseconds to 100-nanosecond ticks (1 ms = 10,000 ticks) // This matches the C++ implementation: std::chrono::duration_cast(std::chrono::milliseconds(milliseconds)) return TimeSpan.FromTicks(milliseconds * 10_000L); } /// /// Returns the given duration in seconds. /// public static double ToSeconds(TimeSpan duration) { return duration.TotalSeconds; } /// /// Creates a Time from Universal Time Scale ticks. /// public static DateTime FromUniversal(long ticks) { // Universal Time Scale epoch is January 1, 1 at the start of day in UTC // We need to convert from UTS epoch to .NET DateTime epoch (January 1, 0001) // UTS epoch offset: 719162 days = January 1, 1 // .NET DateTime epoch: January 1, 0001 // So we can use DateTime directly since both use the same epoch return new DateTime(ticks, DateTimeKind.Utc); } /// /// Outputs the Universal Time Scale timestamp for a given Time. /// public static long ToUniversal(DateTime time) { return time.ToUniversalTime().Ticks; } /// /// CPU time consumed by the thread so far, in seconds. /// public static double GetThreadCpuTimeSeconds() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // Windows implementation would use GetThreadTimes // For now, return 0 on Windows return 0.0; } else { // Linux implementation using clock_gettime with CLOCK_THREAD_CPUTIME_ID var timespec = new Timespec(); if (clock_gettime(ClockId.CLOCK_THREAD_CPUTIME_ID, ref timespec) == 0) { return timespec.tv_sec + 1e-9 * timespec.tv_nsec; } return 0.0; } } [StructLayout(LayoutKind.Sequential)] private struct Timespec { public long tv_sec; // seconds public long tv_nsec; // nanoseconds } private enum ClockId { CLOCK_REALTIME = 0, CLOCK_MONOTONIC = 1, CLOCK_PROCESS_CPUTIME_ID = 2, CLOCK_THREAD_CPUTIME_ID = 3, CLOCK_MONOTONIC_RAW = 4, } [LibraryImport("libc", SetLastError = true)] private static partial int clock_gettime(ClockId clockid, ref Timespec tp); }