| Index: base/message_loop/message_pump_mac.mm
|
| diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm
|
| index 891cc347448ff70b30f9357ff431d46aad613f59..25aac17f2672c78b503f6bd9aa35b8be95a6bcc3 100644
|
| --- a/base/message_loop/message_pump_mac.mm
|
| +++ b/base/message_loop/message_pump_mac.mm
|
| @@ -4,6 +4,7 @@
|
|
|
| #import "base/message_loop/message_pump_mac.h"
|
|
|
| +#include <dlfcn.h>
|
| #import <Foundation/Foundation.h>
|
|
|
| #include <limits>
|
| @@ -12,6 +13,7 @@
|
| #include "base/format_macros.h"
|
| #include "base/logging.h"
|
| #include "base/mac/scoped_cftyperef.h"
|
| +#include "base/message_loop/timer_slack.h"
|
| #include "base/metrics/histogram.h"
|
| #include "base/run_loop.h"
|
| #include "base/strings/stringprintf.h"
|
| @@ -35,6 +37,33 @@ const CFTimeInterval kCFTimeIntervalMax =
|
| bool g_not_using_cr_app = false;
|
| #endif
|
|
|
| +// Call through to CFRunLoopTimerSetTolerance(), which is only available on
|
| +// OS X 10.9.
|
| +void SetTimerTolerance(CFRunLoopTimerRef timer, CFTimeInterval tolerance) {
|
| + typedef void (*CFRunLoopTimerSetTolerancePtr)(CFRunLoopTimerRef timer,
|
| + CFTimeInterval tolerance);
|
| +
|
| + static CFRunLoopTimerSetTolerancePtr settimertolerance_function_ptr;
|
| +
|
| + static dispatch_once_t get_timer_tolerance_function_ptr_once;
|
| + dispatch_once(&get_timer_tolerance_function_ptr_once, ^{
|
| + NSBundle* bundle =[NSBundle
|
| + bundleWithPath:@"/System/Library/Frameworks/CoreFoundation.framework"];
|
| + const char* path = [[bundle executablePath] fileSystemRepresentation];
|
| + CHECK(path);
|
| + void* library_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
|
| + CHECK(library_handle) << dlerror();
|
| + settimertolerance_function_ptr =
|
| + reinterpret_cast<CFRunLoopTimerSetTolerancePtr>(
|
| + dlsym(library_handle, "CFRunLoopTimerSetTolerance"));
|
| +
|
| + dlclose(library_handle);
|
| + });
|
| +
|
| + if (settimertolerance_function_ptr)
|
| + settimertolerance_function_ptr(timer, tolerance);
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace base {
|
| @@ -282,6 +311,7 @@ class MessagePumpInstrumentation {
|
| MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
| : delegate_(NULL),
|
| delayed_work_fire_time_(kCFTimeIntervalMax),
|
| + timer_slack_(base::TIMER_SLACK_NONE),
|
| nesting_level_(0),
|
| run_nesting_level_(0),
|
| deepest_nesting_level_(0),
|
| @@ -438,6 +468,15 @@ void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
|
| TimeDelta delta = delayed_work_time - TimeTicks::Now();
|
| delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF();
|
| CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_);
|
| + if (timer_slack_ == TIMER_SLACK_MAXIMUM) {
|
| + SetTimerTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5);
|
| + } else {
|
| + SetTimerTolerance(delayed_work_timer_, 0);
|
| + }
|
| +}
|
| +
|
| +void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) {
|
| + timer_slack_ = timer_slack;
|
| }
|
|
|
| // Called from the run loop.
|
|
|