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