Skip to content

Commit

Permalink
Added 100ns as timestamp resolution.
Browse files Browse the repository at this point in the history
  • Loading branch information
crowbar27 committed Jun 25, 2023
1 parent d792e63 commit 4cc2a94
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ namespace power_overwhelming {
/// </summary>
microseconds,

/// <summary>
/// Timestamp is specified in units of hundred nanoseconds (the native
/// quantity of many Windows APIs).
/// </summary>
hundred_nanoseconds,

/// <summary>
/// Timestamp is specified in nanoseconds (Billionth of a second).
/// </summary>
Expand Down
9 changes: 6 additions & 3 deletions power_overwhelming/src/timestamp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
*/
visus::power_overwhelming::timestamp_type
visus::power_overwhelming::detail::convert(
const timestamp_type fileTime,
const timestamp_type file_time,
const timestamp_resolution resolution) {
using namespace std::chrono;
duration<decltype(fileTime), filetime_period> ft(fileTime);
duration<decltype(file_time), filetime_period> ft(file_time);

switch (resolution) {
case timestamp_resolution::microseconds:
Expand All @@ -26,11 +26,14 @@ visus::power_overwhelming::detail::convert(
case timestamp_resolution::nanoseconds:
return duration_cast<nanoseconds>(ft).count();

case timestamp_resolution::hundred_nanoseconds:
return file_time;

case timestamp_resolution::seconds:
return duration_cast<seconds>(ft).count();

default:
return fileTime;
return file_time;
}
}

Expand Down
11 changes: 6 additions & 5 deletions power_overwhelming/src/timestamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,27 @@ namespace detail {
/// This API is only exposed for unit tests and should not be accessed by
/// any other clients.
/// </remarks>
/// <param name="fileTime">The file time value in 100ns units.</param>
/// <param name="file_time">The file time value in 100ns units.</param>
/// <param name="resolution">The desired resolution of the timestamp.
/// </param>
/// <returns>The timestamp in the requested resolution.</returns>
timestamp_type POWER_OVERWHELMING_API convert(const timestamp_type fileTime,
timestamp_type POWER_OVERWHELMING_API convert(
const timestamp_type file_time,
const timestamp_resolution resolution);

#if defined(_WIN32)
/// <summary>
/// Convert the given raw <see cref="LARGE_INTEGER" /> to a timestamp of the
/// specified resolution.
/// </summary>
/// <param name="fileTime">The file time value in 100ns units.</param>
/// <param name="file_time">The file time value in 100ns units.</param>
/// <param name="resolution">The desired resolution of the timestamp.
/// </param>
/// <returns>The timestamp in the requested resolution.</returns>
inline POWER_OVERWHELMING_API decltype(LARGE_INTEGER::QuadPart) convert(
const LARGE_INTEGER& fileTime,
const LARGE_INTEGER& file_time,
const timestamp_resolution resolution) {
return convert(fileTime.QuadPart, resolution);
return convert(file_time.QuadPart, resolution);
}
#endif /* defined(_WIN32) */

Expand Down
6 changes: 5 additions & 1 deletion power_overwhelming/src/timestamp.inl
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ visus::power_overwhelming::detail::convert(
TDuration>& timestamp,
_In_ const timestamp_resolution resolution) {
using namespace std::chrono;
typedef duration<timestamp_type, filetime_period> filetime_dur;

// The offset of the FILETIME epoch to the UNIX epoch.
const auto dz = duration<timestamp_type,
detail::filetime_period>(11644473600000LL);
detail::filetime_period>(116444736000000000LL);

// Find out what the difference between the time point and the UNIX
// epoch is. Because we cannot rely on the epoch of the STL clock being the
Expand All @@ -72,6 +73,9 @@ visus::power_overwhelming::detail::convert(

// Transform the origin of the timestamp clock to the origin of FILETIME.
switch (resolution) {
case timestamp_resolution::hundred_nanoseconds:
return duration_cast<filetime_dur>(dt + dz).count();

case timestamp_resolution::microseconds:
return duration_cast<microseconds>(dt + dz).count();

Expand Down
59 changes: 46 additions & 13 deletions test/timestamp_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,36 +38,69 @@ namespace test {
this->_system_zero = std::chrono::system_clock::from_time_t(0);
}

TEST_METHOD(test_convert) {
auto a = detail::convert(std::chrono::system_clock::from_time_t(0), timestamp_resolution::hundred_nanoseconds);
Assert::AreEqual(this->_filetime_zero, a, L"Unix epoch as FILETIME", LINE_INFO());
}

TEST_METHOD(test_microseconds) {
typedef std::chrono::microseconds unit;
static const auto resolution = timestamp_resolution::microseconds;
const auto max_dt = std::chrono::duration_cast<unit>(std::chrono::milliseconds(100)).count();

auto n = std::chrono::system_clock::now();
auto t = detail::create_timestamp(timestamp_resolution::microseconds);
auto s = std::chrono::duration_cast<std::chrono::microseconds>(n - this->_system_zero).count();
auto z = detail::convert(this->_filetime_zero, timestamp_resolution::microseconds);
Assert::IsTrue(s - z - t < 1000000, L"timestamp microsecond", LINE_INFO());
auto t = detail::create_timestamp(resolution);
auto s = std::chrono::duration_cast<unit>(n - this->_system_zero).count();
auto z = detail::convert(this->_filetime_zero, resolution);
Assert::IsTrue(s - z - t < max_dt, L"timestamp microsecond", LINE_INFO());
}

TEST_METHOD(test_milliseconds) {
typedef std::chrono::milliseconds unit;
static const auto resolution = timestamp_resolution::milliseconds;
const auto max_dt = std::chrono::duration_cast<unit>(std::chrono::milliseconds(100)).count();

auto n = std::chrono::system_clock::now();
auto t = detail::create_timestamp(timestamp_resolution::milliseconds);
auto s = std::chrono::duration_cast<std::chrono::milliseconds>(n - this->_system_zero).count();
auto z = detail::convert(this->_filetime_zero, timestamp_resolution::milliseconds);
Assert::IsTrue(t - z - s < 1000, L"timestamp millisecond", LINE_INFO());
Assert::IsTrue(t - z - s < max_dt, L"timestamp millisecond", LINE_INFO());
}

TEST_METHOD(test_hundred_nanoseconds) {
typedef std::chrono::duration<std::chrono::system_clock::duration::rep, detail::filetime_period> unit;
static const auto resolution = timestamp_resolution::milliseconds;
const auto max_dt = std::chrono::duration_cast<unit>(std::chrono::milliseconds(100)).count();

auto n = std::chrono::system_clock::now();
auto t = detail::create_timestamp(resolution);
auto s = std::chrono::duration_cast<unit>(n - this->_system_zero).count();
auto z = detail::convert(this->_filetime_zero, resolution);
Assert::IsTrue(t - z - s < max_dt, L"timestamp 100 nanoseconds", LINE_INFO());
}

TEST_METHOD(test_nanoseconds) {
typedef std::chrono::milliseconds unit;
static const auto resolution = timestamp_resolution::milliseconds;
const auto max_dt = std::chrono::duration_cast<unit>(std::chrono::milliseconds(100)).count();

auto n = std::chrono::system_clock::now();
auto t = detail::create_timestamp(timestamp_resolution::nanoseconds);
auto s = std::chrono::duration_cast<std::chrono::nanoseconds>(n - this->_system_zero).count();
auto z = detail::convert(this->_filetime_zero, timestamp_resolution::nanoseconds);
Assert::IsTrue(t - z - s < 1000000000, L"timestamp nanosecond", LINE_INFO());
auto t = detail::create_timestamp(resolution);
auto s = std::chrono::duration_cast<unit>(n - this->_system_zero).count();
auto z = detail::convert(this->_filetime_zero, resolution);
Assert::IsTrue(t - z - s < max_dt, L"timestamp nanosecond", LINE_INFO());
}

TEST_METHOD(test_seconds) {
typedef std::chrono::seconds unit;
static const auto resolution = timestamp_resolution::seconds;
const auto max_dt = std::chrono::duration_cast<unit>(std::chrono::milliseconds(100)).count();

auto n = std::chrono::system_clock::now();
auto t = detail::create_timestamp(timestamp_resolution::seconds);
auto s = std::chrono::duration_cast<std::chrono::seconds>(n - this->_system_zero).count();
auto z = detail::convert(this->_filetime_zero, timestamp_resolution::seconds);
Assert::IsTrue(s - z - t < 1, L"timestamp second", LINE_INFO());
auto t = detail::create_timestamp(resolution);
auto s = std::chrono::duration_cast<unit>(n - this->_system_zero).count();
auto z = detail::convert(this->_filetime_zero, resolution);
Assert::IsTrue(s - z - t < max_dt, L"timestamp second", LINE_INFO());
}

private:
Expand Down

0 comments on commit 4cc2a94

Please sign in to comment.