| 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 370e351ec9cd449c9c281da177dedf0db8aac7c0..305234b8170a610682ac271181471c72ee5e89ef 100644
|
| --- a/base/message_loop/message_pump_mac.mm
|
| +++ b/base/message_loop/message_pump_mac.mm
|
| @@ -44,39 +44,8 @@ const CFStringRef kAllModes[] = {
|
| CFSTR("NSUnhighlightMenuRunLoopMode"),
|
| };
|
|
|
| -void CFRunLoopAddSourceToAllModes(CFRunLoopRef rl, CFRunLoopSourceRef source) {
|
| - for (const CFStringRef& mode : kAllModes)
|
| - CFRunLoopAddSource(rl, source, mode);
|
| -}
|
| -
|
| -void CFRunLoopRemoveSourceFromAllModes(CFRunLoopRef rl,
|
| - CFRunLoopSourceRef source) {
|
| - for (const CFStringRef& mode : kAllModes)
|
| - CFRunLoopRemoveSource(rl, source, mode);
|
| -}
|
| -
|
| -void CFRunLoopAddTimerToAllModes(CFRunLoopRef rl, CFRunLoopTimerRef timer) {
|
| - for (const CFStringRef& mode : kAllModes)
|
| - CFRunLoopAddTimer(rl, timer, mode);
|
| -}
|
| -
|
| -void CFRunLoopRemoveTimerFromAllModes(CFRunLoopRef rl,
|
| - CFRunLoopTimerRef timer) {
|
| - for (const CFStringRef& mode : kAllModes)
|
| - CFRunLoopRemoveTimer(rl, timer, mode);
|
| -}
|
| -
|
| -void CFRunLoopAddObserverToAllModes(CFRunLoopRef rl,
|
| - CFRunLoopObserverRef observer) {
|
| - for (const CFStringRef& mode : kAllModes)
|
| - CFRunLoopAddObserver(rl, observer, mode);
|
| -}
|
| -
|
| -void CFRunLoopRemoveObserverFromAllModes(CFRunLoopRef rl,
|
| - CFRunLoopObserverRef observer) {
|
| - for (const CFStringRef& mode : kAllModes)
|
| - CFRunLoopRemoveObserver(rl, observer, mode);
|
| -}
|
| +// Mask that determines which modes in |kAllModes| to use.
|
| +enum { kCommonModeMask = 0x1, kAllModesMask = ~0 };
|
|
|
| void NoOp(void* info) {
|
| }
|
| @@ -154,50 +123,61 @@ class MessagePumpScopedAutoreleasePool {
|
| DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool);
|
| };
|
|
|
| -#if !defined(OS_IOS)
|
| -// This function uses private API to modify a test timer's valid state and
|
| -// uses public API to confirm that the private API changed the correct bit.
|
| -// static
|
| -bool MessagePumpCFRunLoopBase::CanInvalidateCFRunLoopTimers() {
|
| - CFRunLoopTimerContext timer_context = CFRunLoopTimerContext();
|
| - timer_context.info = nullptr;
|
| - ScopedCFTypeRef<CFRunLoopTimerRef> test_timer(
|
| - CFRunLoopTimerCreate(NULL, // allocator
|
| - kCFTimeIntervalMax, // fire time
|
| - kCFTimeIntervalMax, // interval
|
| - 0, // flags
|
| - 0, // priority
|
| - nullptr, &timer_context));
|
| - // Should be valid from the start.
|
| - if (!CFRunLoopTimerIsValid(test_timer)) {
|
| - return false;
|
| - }
|
| - // Confirm that the private API can mark the timer invalid.
|
| - __ChromeCFRunLoopTimerSetValid(test_timer, false);
|
| - if (CFRunLoopTimerIsValid(test_timer)) {
|
| - return false;
|
| - }
|
| - // Confirm that the private API can mark the timer valid.
|
| - __ChromeCFRunLoopTimerSetValid(test_timer, true);
|
| - return CFRunLoopTimerIsValid(test_timer);
|
| +// Must be called on the run loop thread.
|
| +void MessagePumpCFRunLoopBase::Run(Delegate* delegate) {
|
| + // nesting_level_ will be incremented in EnterExitRunLoop, so set
|
| + // run_nesting_level_ accordingly.
|
| + int last_run_nesting_level = run_nesting_level_;
|
| + run_nesting_level_ = nesting_level_ + 1;
|
| +
|
| + Delegate* last_delegate = delegate_;
|
| + SetDelegate(delegate);
|
| +
|
| + DoRun(delegate);
|
| +
|
| + // Restore the previous state of the object.
|
| + SetDelegate(last_delegate);
|
| + run_nesting_level_ = last_run_nesting_level;
|
| }
|
| -#endif // !defined(OS_IOS)
|
|
|
| -// static
|
| -void MessagePumpCFRunLoopBase::ChromeCFRunLoopTimerSetValid(
|
| - CFRunLoopTimerRef timer,
|
| - bool valid) {
|
| -#if !defined(OS_IOS)
|
| - static bool can_invalidate_timers = CanInvalidateCFRunLoopTimers();
|
| - if (can_invalidate_timers) {
|
| - __ChromeCFRunLoopTimerSetValid(timer, valid);
|
| +// May be called on any thread.
|
| +void MessagePumpCFRunLoopBase::ScheduleWork() {
|
| + CFRunLoopSourceSignal(work_source_);
|
| + CFRunLoopWakeUp(run_loop_);
|
| +}
|
| +
|
| +// Must be called on the run loop thread.
|
| +void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
|
| + const TimeTicks& delayed_work_time) {
|
| + TimeDelta delta = delayed_work_time - TimeTicks::Now();
|
| + delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF();
|
| +
|
| + // Flip the timer's validation bit just before setting the new fire time. Do
|
| + // this now because CFRunLoopTimerSetNextFireDate() likely checks the validity
|
| + // of a timer before proceeding to set its fire date. Making the timer valid
|
| + // now won't have any side effects (such as a premature firing of the timer)
|
| + // because we're only flipping a bit.
|
| + //
|
| + // Please see the comment in RunDelayedWorkTimer() for more info on the whys
|
| + // of invalidation.
|
| + ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true);
|
| +
|
| + CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_);
|
| + if (timer_slack_ == TIMER_SLACK_MAXIMUM) {
|
| + CFRunLoopTimerSetTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5);
|
| + } else {
|
| + CFRunLoopTimerSetTolerance(delayed_work_timer_, 0);
|
| }
|
| -#endif // !defined(OS_IOS)
|
| +}
|
| +
|
| +void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) {
|
| + timer_slack_ = timer_slack;
|
| }
|
|
|
| // Must be called on the run loop thread.
|
| -MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
| - : delegate_(NULL),
|
| +MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase(int mode_mask)
|
| + : mode_mask_(mode_mask),
|
| + delegate_(NULL),
|
| delayed_work_fire_time_(kCFTimeIntervalMax),
|
| timer_slack_(base::TIMER_SLACK_NONE),
|
| nesting_level_(0),
|
| @@ -220,7 +200,7 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
| 0, // priority
|
| RunDelayedWorkTimer,
|
| &timer_context);
|
| - CFRunLoopAddTimerToAllModes(run_loop_, delayed_work_timer_);
|
| + InvokeForEnabledModes(&CFRunLoopAddTimer, delayed_work_timer_);
|
|
|
| CFRunLoopSourceContext source_context = CFRunLoopSourceContext();
|
| source_context.info = this;
|
| @@ -228,19 +208,19 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
| work_source_ = CFRunLoopSourceCreate(NULL, // allocator
|
| 1, // priority
|
| &source_context);
|
| - CFRunLoopAddSourceToAllModes(run_loop_, work_source_);
|
| + InvokeForEnabledModes(&CFRunLoopAddSource, work_source_);
|
|
|
| source_context.perform = RunIdleWorkSource;
|
| idle_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
|
| 2, // priority
|
| &source_context);
|
| - CFRunLoopAddSourceToAllModes(run_loop_, idle_work_source_);
|
| + InvokeForEnabledModes(&CFRunLoopAddSource, idle_work_source_);
|
|
|
| source_context.perform = RunNestingDeferredWorkSource;
|
| nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
|
| 0, // priority
|
| &source_context);
|
| - CFRunLoopAddSourceToAllModes(run_loop_, nesting_deferred_work_source_);
|
| + InvokeForEnabledModes(&CFRunLoopAddSource, nesting_deferred_work_source_);
|
|
|
| CFRunLoopObserverContext observer_context = CFRunLoopObserverContext();
|
| observer_context.info = this;
|
| @@ -250,7 +230,7 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
| 0, // priority
|
| PreWaitObserver,
|
| &observer_context);
|
| - CFRunLoopAddObserverToAllModes(run_loop_, pre_wait_observer_);
|
| + InvokeForEnabledModes(&CFRunLoopAddObserver, pre_wait_observer_);
|
|
|
| pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator
|
| kCFRunLoopBeforeSources,
|
| @@ -258,7 +238,7 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
| 0, // priority
|
| PreSourceObserver,
|
| &observer_context);
|
| - CFRunLoopAddObserverToAllModes(run_loop_, pre_source_observer_);
|
| + InvokeForEnabledModes(&CFRunLoopAddObserver, pre_source_observer_);
|
|
|
| enter_exit_observer_ = CFRunLoopObserverCreate(NULL, // allocator
|
| kCFRunLoopEntry |
|
| @@ -267,54 +247,28 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
| 0, // priority
|
| EnterExitObserver,
|
| &observer_context);
|
| - CFRunLoopAddObserverToAllModes(run_loop_, enter_exit_observer_);
|
| + InvokeForEnabledModes(&CFRunLoopAddObserver, enter_exit_observer_);
|
| }
|
|
|
| // Ideally called on the run loop thread. If other run loops were running
|
| // lower on the run loop thread's stack when this object was created, the
|
| // same number of run loops must be running when this object is destroyed.
|
| MessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() {
|
| - CFRunLoopRemoveObserverFromAllModes(run_loop_, enter_exit_observer_);
|
| - CFRelease(enter_exit_observer_);
|
| -
|
| - CFRunLoopRemoveObserverFromAllModes(run_loop_, pre_source_observer_);
|
| - CFRelease(pre_source_observer_);
|
| -
|
| - CFRunLoopRemoveObserverFromAllModes(run_loop_, pre_wait_observer_);
|
| - CFRelease(pre_wait_observer_);
|
| -
|
| - CFRunLoopRemoveSourceFromAllModes(run_loop_, nesting_deferred_work_source_);
|
| - CFRelease(nesting_deferred_work_source_);
|
| -
|
| - CFRunLoopRemoveSourceFromAllModes(run_loop_, idle_work_source_);
|
| - CFRelease(idle_work_source_);
|
| -
|
| - CFRunLoopRemoveSourceFromAllModes(run_loop_, work_source_);
|
| - CFRelease(work_source_);
|
| -
|
| - CFRunLoopRemoveTimerFromAllModes(run_loop_, delayed_work_timer_);
|
| + for (const CFRunLoopObserverRef& observer :
|
| + {enter_exit_observer_, pre_source_observer_, pre_wait_observer_}) {
|
| + InvokeForEnabledModes(&CFRunLoopRemoveObserver, observer);
|
| + CFRelease(observer);
|
| + }
|
| + for (const CFRunLoopSourceRef& source :
|
| + {nesting_deferred_work_source_, idle_work_source_, work_source_}) {
|
| + InvokeForEnabledModes(&CFRunLoopRemoveSource, source);
|
| + CFRelease(source);
|
| + }
|
| + InvokeForEnabledModes(&CFRunLoopRemoveTimer, delayed_work_timer_);
|
| CFRelease(delayed_work_timer_);
|
| -
|
| CFRelease(run_loop_);
|
| }
|
|
|
| -// Must be called on the run loop thread.
|
| -void MessagePumpCFRunLoopBase::Run(Delegate* delegate) {
|
| - // nesting_level_ will be incremented in EnterExitRunLoop, so set
|
| - // run_nesting_level_ accordingly.
|
| - int last_run_nesting_level = run_nesting_level_;
|
| - run_nesting_level_ = nesting_level_ + 1;
|
| -
|
| - Delegate* last_delegate = delegate_;
|
| - SetDelegate(delegate);
|
| -
|
| - DoRun(delegate);
|
| -
|
| - // Restore the previous state of the object.
|
| - SetDelegate(last_delegate);
|
| - run_nesting_level_ = last_run_nesting_level;
|
| -}
|
| -
|
| void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) {
|
| delegate_ = delegate;
|
|
|
| @@ -333,38 +287,61 @@ void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) {
|
| }
|
| }
|
|
|
| -// May be called on any thread.
|
| -void MessagePumpCFRunLoopBase::ScheduleWork() {
|
| - CFRunLoopSourceSignal(work_source_);
|
| - CFRunLoopWakeUp(run_loop_);
|
| +// Base version returns a standard NSAutoreleasePool.
|
| +AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() {
|
| + return [[NSAutoreleasePool alloc] init];
|
| }
|
|
|
| -// Must be called on the run loop thread.
|
| -void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
|
| - const TimeTicks& delayed_work_time) {
|
| - TimeDelta delta = delayed_work_time - TimeTicks::Now();
|
| - delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF();
|
| -
|
| - // Flip the timer's validation bit just before setting the new fire time. Do
|
| - // this now because CFRunLoopTimerSetNextFireDate() likely checks the validity
|
| - // of a timer before proceeding to set its fire date. Making the timer valid
|
| - // now won't have any side effects (such as a premature firing of the timer)
|
| - // because we're only flipping a bit.
|
| - //
|
| - // Please see the comment in RunDelayedWorkTimer() for more info on the whys
|
| - // of invalidation.
|
| - ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true);
|
| +template <typename Argument>
|
| +void MessagePumpCFRunLoopBase::InvokeForEnabledModes(void method(CFRunLoopRef,
|
| + Argument,
|
| + CFStringRef),
|
| + Argument argument) {
|
| + for (size_t i = 0; i < arraysize(kAllModes); ++i) {
|
| + if (mode_mask_ & (0x1 << i))
|
| + method(run_loop_, argument, kAllModes[i]);
|
| + }
|
| +}
|
|
|
| - CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_);
|
| - if (timer_slack_ == TIMER_SLACK_MAXIMUM) {
|
| - CFRunLoopTimerSetTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5);
|
| - } else {
|
| - CFRunLoopTimerSetTolerance(delayed_work_timer_, 0);
|
| +#if !defined(OS_IOS)
|
| +// This function uses private API to modify a test timer's valid state and
|
| +// uses public API to confirm that the private API changed the correct bit.
|
| +// static
|
| +bool MessagePumpCFRunLoopBase::CanInvalidateCFRunLoopTimers() {
|
| + CFRunLoopTimerContext timer_context = CFRunLoopTimerContext();
|
| + timer_context.info = nullptr;
|
| + ScopedCFTypeRef<CFRunLoopTimerRef> test_timer(
|
| + CFRunLoopTimerCreate(NULL, // allocator
|
| + kCFTimeIntervalMax, // fire time
|
| + kCFTimeIntervalMax, // interval
|
| + 0, // flags
|
| + 0, // priority
|
| + nullptr, &timer_context));
|
| + // Should be valid from the start.
|
| + if (!CFRunLoopTimerIsValid(test_timer)) {
|
| + return false;
|
| + }
|
| + // Confirm that the private API can mark the timer invalid.
|
| + __ChromeCFRunLoopTimerSetValid(test_timer, false);
|
| + if (CFRunLoopTimerIsValid(test_timer)) {
|
| + return false;
|
| }
|
| + // Confirm that the private API can mark the timer valid.
|
| + __ChromeCFRunLoopTimerSetValid(test_timer, true);
|
| + return CFRunLoopTimerIsValid(test_timer);
|
| }
|
| +#endif // !defined(OS_IOS)
|
|
|
| -void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) {
|
| - timer_slack_ = timer_slack;
|
| +// static
|
| +void MessagePumpCFRunLoopBase::ChromeCFRunLoopTimerSetValid(
|
| + CFRunLoopTimerRef timer,
|
| + bool valid) {
|
| +#if !defined(OS_IOS)
|
| + static bool can_invalidate_timers = CanInvalidateCFRunLoopTimers();
|
| + if (can_invalidate_timers) {
|
| + __ChromeCFRunLoopTimerSetValid(timer, valid);
|
| + }
|
| +#endif // !defined(OS_IOS)
|
| }
|
|
|
| // Called from the run loop.
|
| @@ -639,14 +616,8 @@ void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer,
|
| void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) {
|
| }
|
|
|
| -// Base version returns a standard NSAutoreleasePool.
|
| -AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() {
|
| - return [[NSAutoreleasePool alloc] init];
|
| -}
|
| -
|
| MessagePumpCFRunLoop::MessagePumpCFRunLoop()
|
| - : quit_pending_(false) {
|
| -}
|
| + : MessagePumpCFRunLoopBase(kCommonModeMask), quit_pending_(false) {}
|
|
|
| MessagePumpCFRunLoop::~MessagePumpCFRunLoop() {}
|
|
|
| @@ -697,17 +668,17 @@ void MessagePumpCFRunLoop::EnterExitRunLoop(CFRunLoopActivity activity) {
|
| }
|
|
|
| MessagePumpNSRunLoop::MessagePumpNSRunLoop()
|
| - : keep_running_(true) {
|
| + : MessagePumpCFRunLoopBase(kCommonModeMask), keep_running_(true) {
|
| CFRunLoopSourceContext source_context = CFRunLoopSourceContext();
|
| source_context.perform = NoOp;
|
| quit_source_ = CFRunLoopSourceCreate(NULL, // allocator
|
| 0, // priority
|
| &source_context);
|
| - CFRunLoopAddSourceToAllModes(run_loop(), quit_source_);
|
| + InvokeForEnabledModes(&CFRunLoopAddSource, quit_source_);
|
| }
|
|
|
| MessagePumpNSRunLoop::~MessagePumpNSRunLoop() {
|
| - CFRunLoopRemoveSourceFromAllModes(run_loop(), quit_source_);
|
| + InvokeForEnabledModes(&CFRunLoopRemoveSource, quit_source_);
|
| CFRelease(quit_source_);
|
| }
|
|
|
| @@ -729,8 +700,7 @@ void MessagePumpNSRunLoop::Quit() {
|
|
|
| #if defined(OS_IOS)
|
| MessagePumpUIApplication::MessagePumpUIApplication()
|
| - : run_loop_(NULL) {
|
| -}
|
| + : MessagePumpCFRunLoopBase(kCommonModeMask), run_loop_(NULL) {}
|
|
|
| MessagePumpUIApplication::~MessagePumpUIApplication() {}
|
|
|
| @@ -752,9 +722,9 @@ void MessagePumpUIApplication::Attach(Delegate* delegate) {
|
| #else
|
|
|
| MessagePumpNSApplication::MessagePumpNSApplication()
|
| - : keep_running_(true),
|
| - running_own_loop_(false) {
|
| -}
|
| + : MessagePumpCFRunLoopBase(kAllModesMask),
|
| + keep_running_(true),
|
| + running_own_loop_(false) {}
|
|
|
| MessagePumpNSApplication::~MessagePumpNSApplication() {}
|
|
|
|
|