| /* |
| * Copyright 2008 The WebRTC Project Authors. All rights reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "webrtc/base/timing.h" |
| #include "webrtc/base/timeutils.h" |
| |
| #if defined(WEBRTC_POSIX) |
| #include <errno.h> |
| #include <math.h> |
| #include <sys/time.h> |
| #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) |
| #include <mach/mach.h> |
| #include <mach/clock.h> |
| #endif |
| #elif defined(WEBRTC_WIN) |
| #include <sys/timeb.h> |
| #include "webrtc/base/win32.h" |
| #endif |
| |
| namespace rtc { |
| |
| Timing::Timing() { |
| #if defined(WEBRTC_WIN) |
| // This may fail, but we handle failure gracefully in the methods |
| // that use it (use alternative sleep method). |
| // |
| // TODO: Make it possible for user to tell if IdleWait will |
| // be done at lesser resolution because of this. |
| timer_handle_ = CreateWaitableTimer(NULL, // Security attributes. |
| FALSE, // Manual reset? |
| NULL); // Timer name. |
| #endif |
| } |
| |
| Timing::~Timing() { |
| #if defined(WEBRTC_WIN) |
| if (timer_handle_ != NULL) |
| CloseHandle(timer_handle_); |
| #endif |
| } |
| |
| // static |
| double Timing::WallTimeNow() { |
| #if defined(WEBRTC_POSIX) |
| struct timeval time; |
| gettimeofday(&time, NULL); |
| // Convert from second (1.0) and microsecond (1e-6). |
| return (static_cast<double>(time.tv_sec) + |
| static_cast<double>(time.tv_usec) * 1.0e-6); |
| |
| #elif defined(WEBRTC_WIN) |
| struct _timeb time; |
| _ftime(&time); |
| // Convert from second (1.0) and milliseconds (1e-3). |
| return (static_cast<double>(time.time) + |
| static_cast<double>(time.millitm) * 1.0e-3); |
| #endif |
| } |
| |
| double Timing::TimerNow() { |
| return (static_cast<double>(TimeNanos()) / kNumNanosecsPerSec); |
| } |
| |
| double Timing::BusyWait(double period) { |
| double start_time = TimerNow(); |
| while (TimerNow() - start_time < period) { |
| } |
| return TimerNow() - start_time; |
| } |
| |
| double Timing::IdleWait(double period) { |
| double start_time = TimerNow(); |
| |
| #if defined(WEBRTC_POSIX) |
| double sec_int, sec_frac = modf(period, &sec_int); |
| struct timespec ts; |
| ts.tv_sec = static_cast<time_t>(sec_int); |
| ts.tv_nsec = static_cast<long>(sec_frac * 1.0e9); // NOLINT |
| |
| // NOTE(liulk): for the NOLINT above, long is the appropriate POSIX |
| // type. |
| |
| // POSIX nanosleep may be interrupted by signals. |
| while (nanosleep(&ts, &ts) == -1 && errno == EINTR) { |
| } |
| |
| #elif defined(WEBRTC_WIN) |
| if (timer_handle_ != NULL) { |
| LARGE_INTEGER due_time; |
| |
| // Negative indicates relative time. The unit is 100 nanoseconds. |
| due_time.QuadPart = -LONGLONG(period * 1.0e7); |
| |
| SetWaitableTimer(timer_handle_, &due_time, 0, NULL, NULL, TRUE); |
| WaitForSingleObject(timer_handle_, INFINITE); |
| } else { |
| // Still attempts to sleep with lesser resolution. |
| // The unit is in milliseconds. |
| Sleep(DWORD(period * 1.0e3)); |
| } |
| #endif |
| |
| return TimerNow() - start_time; |
| } |
| |
| } // namespace rtc |