| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "quic/core/quic_clock.h" |
| |
| #include <limits> |
| |
| #include "quic/platform/api/quic_logging.h" |
| |
| namespace quic { |
| |
| QuicClock::QuicClock() |
| : is_calibrated_(false), calibration_offset_(QuicTime::Delta::Zero()) {} |
| |
| QuicClock::~QuicClock() {} |
| |
| QuicTime::Delta QuicClock::ComputeCalibrationOffset() const { |
| // In the ideal world, all we need to do is to return the difference of |
| // WallNow() and Now(). In the real world, things like context switch may |
| // happen between the calls to WallNow() and Now(), causing their difference |
| // to be arbitrarily large, so we repeat the calculation many times and use |
| // the one with the minimum difference as the true offset. |
| int64_t min_offset_us = std::numeric_limits<int64_t>::max(); |
| |
| for (int i = 0; i < 128; ++i) { |
| int64_t now_in_us = (Now() - QuicTime::Zero()).ToMicroseconds(); |
| int64_t wallnow_in_us = |
| static_cast<int64_t>(WallNow().ToUNIXMicroseconds()); |
| |
| int64_t offset_us = wallnow_in_us - now_in_us; |
| if (offset_us < min_offset_us) { |
| min_offset_us = offset_us; |
| } |
| } |
| |
| return QuicTime::Delta::FromMicroseconds(min_offset_us); |
| } |
| |
| void QuicClock::SetCalibrationOffset(QuicTime::Delta offset) { |
| QUICHE_DCHECK(!is_calibrated_) << "A clock should only be calibrated once"; |
| calibration_offset_ = offset; |
| is_calibrated_ = true; |
| } |
| |
| QuicTime QuicClock::ConvertWallTimeToQuicTime( |
| const QuicWallTime& walltime) const { |
| if (is_calibrated_) { |
| int64_t time_in_us = static_cast<int64_t>(walltime.ToUNIXMicroseconds()) - |
| calibration_offset_.ToMicroseconds(); |
| return QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(time_in_us); |
| } |
| |
| // .......................... |
| // | | | |
| // unix epoch |walltime| WallNow() |
| // .......................... |
| // | | | |
| // clock epoch | Now() |
| // result |
| // |
| // result = Now() - (WallNow() - walltime) |
| return Now() - QuicTime::Delta::FromMicroseconds( |
| WallNow() |
| .Subtract(QuicTime::Delta::FromMicroseconds( |
| walltime.ToUNIXMicroseconds())) |
| .ToUNIXMicroseconds()); |
| } |
| |
| } // namespace quic |