147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2008 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/timing.h"
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/timeutils.h"
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <errno.h>
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <math.h>
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sys/time.h>
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <mach/mach.h>
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <mach/clock.h>
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_WIN)
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sys/timeb.h>
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32.h"
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgTiming::Timing() {
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // This may fail, but we handle failure gracefully in the methods
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // that use it (use alternative sleep method).
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO: Make it possible for user to tell if IdleWait will
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // be done at lesser resolution because of this.
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  timer_handle_ = CreateWaitableTimer(NULL,     // Security attributes.
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                      FALSE,    // Manual reset?
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                      NULL);    // Timer name.
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgTiming::~Timing() {
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (timer_handle_ != NULL)
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CloseHandle(timer_handle_);
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
49f247ac6465e0e662dff1e229b31a4efe8f8691a8tommi@webrtc.org// static
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgdouble Timing::WallTimeNow() {
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  struct timeval time;
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  gettimeofday(&time, NULL);
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Convert from second (1.0) and microsecond (1e-6).
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (static_cast<double>(time.tv_sec) +
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          static_cast<double>(time.tv_usec) * 1.0e-6);
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_WIN)
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  struct _timeb time;
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  _ftime(&time);
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Convert from second (1.0) and milliseconds (1e-3).
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (static_cast<double>(time.time) +
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          static_cast<double>(time.millitm) * 1.0e-3);
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgdouble Timing::TimerNow() {
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (static_cast<double>(TimeNanos()) / kNumNanosecsPerSec);
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgdouble Timing::BusyWait(double period) {
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  double start_time = TimerNow();
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (TimerNow() - start_time < period) {
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return TimerNow() - start_time;
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgdouble Timing::IdleWait(double period) {
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  double start_time = TimerNow();
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  double sec_int, sec_frac = modf(period, &sec_int);
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  struct timespec ts;
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ts.tv_sec = static_cast<time_t>(sec_int);
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ts.tv_nsec = static_cast<long>(sec_frac * 1.0e9);  // NOLINT
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // NOTE(liulk): for the NOLINT above, long is the appropriate POSIX
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // type.
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // POSIX nanosleep may be interrupted by signals.
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (nanosleep(&ts, &ts) == -1 && errno == EINTR) {
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_WIN)
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (timer_handle_ != NULL) {
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LARGE_INTEGER due_time;
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Negative indicates relative time.  The unit is 100 nanoseconds.
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    due_time.QuadPart = -LONGLONG(period * 1.0e7);
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetWaitableTimer(timer_handle_, &due_time, 0, NULL, NULL, TRUE);
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    WaitForSingleObject(timer_handle_, INFINITE);
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Still attempts to sleep with lesser resolution.
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // The unit is in milliseconds.
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Sleep(DWORD(period * 1.0e3));
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return TimerNow() - start_time;
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
114