Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: base/message_loop/message_pump_mac.mm

Issue 366873002: Revert of Revert 221427 "Add instrumentation to the MessagePumpMac family ..." (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/message_loop/message_pump_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "base/message_loop/message_pump_mac.h" 5 #import "base/message_loop/message_pump_mac.h"
6 6
7 #include <dlfcn.h> 7 #include <dlfcn.h>
8 #import <Foundation/Foundation.h> 8 #import <Foundation/Foundation.h>
9 9
10 #include <limits> 10 #include <limits>
11 #include <stack>
11 12
13 #include "base/format_macros.h"
12 #include "base/logging.h" 14 #include "base/logging.h"
13 #include "base/mac/scoped_cftyperef.h" 15 #include "base/mac/scoped_cftyperef.h"
14 #include "base/message_loop/timer_slack.h" 16 #include "base/message_loop/timer_slack.h"
17 #include "base/metrics/histogram.h"
15 #include "base/run_loop.h" 18 #include "base/run_loop.h"
19 #include "base/strings/stringprintf.h"
16 #include "base/time/time.h" 20 #include "base/time/time.h"
17 21
18 #if !defined(OS_IOS) 22 #if !defined(OS_IOS)
19 #import <AppKit/AppKit.h> 23 #import <AppKit/AppKit.h>
20 #endif // !defined(OS_IOS) 24 #endif // !defined(OS_IOS)
21 25
22 namespace base { 26 namespace base {
23 27
24 namespace { 28 namespace {
25 29
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 } 116 }
113 ~MessagePumpScopedAutoreleasePool() { 117 ~MessagePumpScopedAutoreleasePool() {
114 [pool_ drain]; 118 [pool_ drain];
115 } 119 }
116 120
117 private: 121 private:
118 NSAutoreleasePool* pool_; 122 NSAutoreleasePool* pool_;
119 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); 123 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool);
120 }; 124 };
121 125
126 // This class is used to instrument the MessagePump to gather various timing
127 // data about when the underlying run loop is entered, when it is waiting, and
128 // when it is servicing its delegate.
129 //
130 // The metrics are gathered as UMA-tracked histograms. To gather the data over
131 // time, sampling is used, such that a new histogram is created for each metric
132 // every |sampling_interval| for |sampling_duration|. After sampling is
133 // complete, this class deletes itself.
134 class MessagePumpInstrumentation {
135 public:
136 // Creates an instrument for the MessagePump on the current thread. Every
137 // |sampling_interval|, a new histogram will be created to track the metrics
138 // over time. After |sampling_duration|, this will delete itself, causing the
139 // WeakPtr to go NULL.
140 static WeakPtr<MessagePumpInstrumentation> Create(
141 const TimeDelta& sampling_interval,
142 const TimeDelta& sampling_duration) {
143 MessagePumpInstrumentation* instrument =
144 new MessagePumpInstrumentation(sampling_interval, sampling_duration);
145 return instrument->weak_ptr_factory_.GetWeakPtr();
146 }
147
148 // Starts the timer that runs the sampling instrumentation. Can be called
149 // multiple times as a noop.
150 void StartIfNeeded() {
151 if (timer_)
152 return;
153
154 sampling_start_time_ = generation_start_time_ = TimeTicks::Now();
155
156 CFRunLoopTimerContext timer_context = { .info = this };
157 timer_.reset(CFRunLoopTimerCreate(
158 NULL, // allocator
159 (Time::Now() + sampling_interval_).ToCFAbsoluteTime(),
160 sampling_interval_.InSecondsF(),
161 0, // flags
162 0, // order
163 &MessagePumpInstrumentation::TimerFired,
164 &timer_context));
165 CFRunLoopAddTimerToAllModes(CFRunLoopGetCurrent(), timer_);
166 }
167
168 // Used to track kCFRunLoopEntry.
169 void LoopEntered() {
170 loop_run_times_.push(TimeTicks::Now());
171 }
172
173 // Used to track kCFRunLoopExit.
174 void LoopExited() {
175 TimeDelta duration = TimeTicks::Now() - loop_run_times_.top();
176 loop_run_times_.pop();
177 GetHistogram(LOOP_CYCLE)->AddTime(duration);
178 }
179
180 // Used to track kCFRunLoopBeforeWaiting.
181 void WaitingStarted() {
182 loop_wait_times_.push(TimeTicks::Now());
183 }
184
185 // Used to track kCFRunLoopAfterWaiting.
186 void WaitingFinished() {
187 TimeDelta duration = TimeTicks::Now() - loop_wait_times_.top();
188 loop_wait_times_.pop();
189 GetHistogram(LOOP_WAIT)->AddTime(duration);
190 }
191
192 // Used to track when the MessagePump will invoke its |delegate|.
193 void WorkSourceEntered(MessagePump::Delegate* delegate) {
194 work_source_times_.push(TimeTicks::Now());
195 if (delegate) {
196 size_t queue_size;
197 TimeDelta queuing_delay;
198 delegate->GetQueueingInformation(&queue_size, &queuing_delay);
199 GetHistogram(QUEUE_SIZE)->Add(queue_size);
200 GetHistogram(QUEUE_DELAY)->AddTime(queuing_delay);
201 }
202 }
203
204 // Used to track the completion of servicing the MessagePump::Delegate.
205 void WorkSourceExited() {
206 TimeDelta duration = TimeTicks::Now() - work_source_times_.top();
207 work_source_times_.pop();
208 GetHistogram(WORK_SOURCE)->AddTime(duration);
209 }
210
211 private:
212 enum HistogramEvent {
213 // Time-based histograms:
214 LOOP_CYCLE, // LoopEntered/LoopExited
215 LOOP_WAIT, // WaitingStarted/WaitingEnded
216 WORK_SOURCE, // WorkSourceExited
217 QUEUE_DELAY, // WorkSourceEntered
218
219 // Value-based histograms:
220 // NOTE: Do not add value-based histograms before this event, only after.
221 QUEUE_SIZE, // WorkSourceEntered
222
223 HISTOGRAM_EVENT_MAX,
224 };
225
226 MessagePumpInstrumentation(const TimeDelta& sampling_interval,
227 const TimeDelta& sampling_duration)
228 : weak_ptr_factory_(this),
229 sampling_interval_(sampling_interval),
230 sampling_duration_(sampling_duration),
231 sample_generation_(0) {
232 // Create all the histogram objects that will be used for sampling.
233 const char kHistogramName[] = "MessagePumpMac.%s.SampleMs.%" PRId64;
234 for (TimeDelta i; i < sampling_duration_; i += sampling_interval_) {
235 int64 sample = i.InMilliseconds();
236
237 // Generate the time-based histograms.
238 for (int j = LOOP_CYCLE; j < QUEUE_SIZE; ++j) {
239 std::string name = StringPrintf(kHistogramName,
240 NameForEnum(static_cast<HistogramEvent>(j)), sample);
241 histograms_[j].push_back(
242 Histogram::FactoryTimeGet(name, TimeDelta::FromMilliseconds(1),
243 sampling_interval_, 50,
244 HistogramBase::kUmaTargetedHistogramFlag));
245 }
246
247 // Generate the value-based histograms.
248 for (int j = QUEUE_SIZE; j < HISTOGRAM_EVENT_MAX; ++j) {
249 std::string name = StringPrintf(kHistogramName,
250 NameForEnum(static_cast<HistogramEvent>(j)), sample);
251 histograms_[j].push_back(
252 Histogram::FactoryGet(name, 1, 10000, 50,
253 HistogramBase::kUmaTargetedHistogramFlag));
254 }
255 }
256 }
257
258 ~MessagePumpInstrumentation() {
259 if (timer_)
260 CFRunLoopTimerInvalidate(timer_);
261 }
262
263 const char* NameForEnum(HistogramEvent event) {
264 switch (event) {
265 case LOOP_CYCLE: return "LoopCycle";
266 case LOOP_WAIT: return "Waiting";
267 case WORK_SOURCE: return "WorkSource";
268 case QUEUE_DELAY: return "QueueingDelay";
269 case QUEUE_SIZE: return "QueueSize";
270 default:
271 NOTREACHED();
272 return NULL;
273 }
274 }
275
276 static void TimerFired(CFRunLoopTimerRef timer, void* context) {
277 static_cast<MessagePumpInstrumentation*>(context)->TimerFired();
278 }
279
280 // Called by the run loop when the sampling_interval_ has elapsed. Advances
281 // the sample_generation_, which controls into which histogram data is
282 // recorded, while recording and accounting for timer skew. Will delete this
283 // object after |sampling_duration_| has elapsed.
284 void TimerFired() {
285 TimeTicks now = TimeTicks::Now();
286 TimeDelta delta = now - generation_start_time_;
287
288 // The timer fired, so advance the generation by at least one.
289 ++sample_generation_;
290
291 // To account for large timer skew/drift, advance the generation by any
292 // more completed intervals.
293 for (TimeDelta skew_advance = delta - sampling_interval_;
294 skew_advance >= sampling_interval_;
295 skew_advance -= sampling_interval_) {
296 ++sample_generation_;
297 }
298
299 generation_start_time_ = now;
300 if (now >= sampling_start_time_ + sampling_duration_)
301 delete this;
302 }
303
304 HistogramBase* GetHistogram(HistogramEvent event) {
305 DCHECK_LT(sample_generation_, histograms_[event].size());
306 return histograms_[event][sample_generation_];
307 }
308
309 // Vends the pointer to the Create()or.
310 WeakPtrFactory<MessagePumpInstrumentation> weak_ptr_factory_;
311
312 // The interval and duration of the sampling.
313 TimeDelta sampling_interval_;
314 TimeDelta sampling_duration_;
315
316 // The time at which sampling started.
317 TimeTicks sampling_start_time_;
318
319 // The timer that advances the sample_generation_ and sets the
320 // generation_start_time_ for the current sample interval.
321 base::ScopedCFTypeRef<CFRunLoopTimerRef> timer_;
322
323 // The two-dimensional array of histograms. The first dimension is the
324 // HistogramEvent type. The second is for the sampling intervals.
325 std::vector<HistogramBase*> histograms_[HISTOGRAM_EVENT_MAX];
326
327 // The index in the second dimension of histograms_, which controls in which
328 // sampled histogram events are recorded.
329 size_t sample_generation_;
330
331 // The last time at which the timer fired. This is used to track timer skew
332 // (i.e. it did not fire on time) and properly account for it when advancing
333 // samle_generation_.
334 TimeTicks generation_start_time_;
335
336 // MessagePump activations can be nested. Use a stack for each of the
337 // possibly reentrant HistogramEvent types to properly balance and calculate
338 // the timing information.
339 std::stack<TimeTicks> loop_run_times_;
340 std::stack<TimeTicks> loop_wait_times_;
341 std::stack<TimeTicks> work_source_times_;
342
343 DISALLOW_COPY_AND_ASSIGN(MessagePumpInstrumentation);
344 };
345
122 // Must be called on the run loop thread. 346 // Must be called on the run loop thread.
123 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() 347 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
124 : delegate_(NULL), 348 : delegate_(NULL),
125 delayed_work_fire_time_(kCFTimeIntervalMax), 349 delayed_work_fire_time_(kCFTimeIntervalMax),
126 timer_slack_(base::TIMER_SLACK_NONE), 350 timer_slack_(base::TIMER_SLACK_NONE),
127 nesting_level_(0), 351 nesting_level_(0),
128 run_nesting_level_(0), 352 run_nesting_level_(0),
129 deepest_nesting_level_(0), 353 deepest_nesting_level_(0),
130 delegateless_work_(false), 354 delegateless_work_(false),
131 delegateless_idle_work_(false) { 355 delegateless_idle_work_(false) {
(...skipping 30 matching lines...) Expand all
162 386
163 source_context.perform = RunNestingDeferredWorkSource; 387 source_context.perform = RunNestingDeferredWorkSource;
164 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator 388 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
165 0, // priority 389 0, // priority
166 &source_context); 390 &source_context);
167 CFRunLoopAddSourceToAllModes(run_loop_, nesting_deferred_work_source_); 391 CFRunLoopAddSourceToAllModes(run_loop_, nesting_deferred_work_source_);
168 392
169 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); 393 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext();
170 observer_context.info = this; 394 observer_context.info = this;
171 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator 395 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator
172 kCFRunLoopBeforeWaiting, 396 kCFRunLoopBeforeWaiting |
397 kCFRunLoopAfterWaiting,
173 true, // repeat 398 true, // repeat
174 0, // priority 399 0, // priority
175 PreWaitObserver, 400 StartOrEndWaitObserver,
176 &observer_context); 401 &observer_context);
177 CFRunLoopAddObserverToAllModes(run_loop_, pre_wait_observer_); 402 CFRunLoopAddObserverToAllModes(run_loop_, pre_wait_observer_);
178 403
179 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator 404 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator
180 kCFRunLoopBeforeSources, 405 kCFRunLoopBeforeSources,
181 true, // repeat 406 true, // repeat
182 0, // priority 407 0, // priority
183 PreSourceObserver, 408 PreSourceObserver,
184 &observer_context); 409 &observer_context);
185 CFRunLoopAddObserverToAllModes(run_loop_, pre_source_observer_); 410 CFRunLoopAddObserverToAllModes(run_loop_, pre_source_observer_);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 CFRunLoopSourceSignal(work_source_); 475 CFRunLoopSourceSignal(work_source_);
251 delegateless_work_ = false; 476 delegateless_work_ = false;
252 } 477 }
253 if (delegateless_idle_work_) { 478 if (delegateless_idle_work_) {
254 CFRunLoopSourceSignal(idle_work_source_); 479 CFRunLoopSourceSignal(idle_work_source_);
255 delegateless_idle_work_ = false; 480 delegateless_idle_work_ = false;
256 } 481 }
257 } 482 }
258 } 483 }
259 484
485 void MessagePumpCFRunLoopBase::EnableInstrumentation() {
486 instrumentation_ = MessagePumpInstrumentation::Create(
487 TimeDelta::FromSeconds(1), TimeDelta::FromSeconds(15));
488 }
489
260 // May be called on any thread. 490 // May be called on any thread.
261 void MessagePumpCFRunLoopBase::ScheduleWork() { 491 void MessagePumpCFRunLoopBase::ScheduleWork() {
262 CFRunLoopSourceSignal(work_source_); 492 CFRunLoopSourceSignal(work_source_);
263 CFRunLoopWakeUp(run_loop_); 493 CFRunLoopWakeUp(run_loop_);
264 } 494 }
265 495
266 // Must be called on the run loop thread. 496 // Must be called on the run loop thread.
267 void MessagePumpCFRunLoopBase::ScheduleDelayedWork( 497 void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
268 const TimeTicks& delayed_work_time) { 498 const TimeTicks& delayed_work_time) {
269 TimeDelta delta = delayed_work_time - TimeTicks::Now(); 499 TimeDelta delta = delayed_work_time - TimeTicks::Now();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 // Called by MessagePumpCFRunLoopBase::RunWorkSource. 536 // Called by MessagePumpCFRunLoopBase::RunWorkSource.
307 bool MessagePumpCFRunLoopBase::RunWork() { 537 bool MessagePumpCFRunLoopBase::RunWork() {
308 if (!delegate_) { 538 if (!delegate_) {
309 // This point can be reached with a NULL delegate_ if Run is not on the 539 // This point can be reached with a NULL delegate_ if Run is not on the
310 // stack but foreign code is spinning the CFRunLoop. Arrange to come back 540 // stack but foreign code is spinning the CFRunLoop. Arrange to come back
311 // here when a delegate is available. 541 // here when a delegate is available.
312 delegateless_work_ = true; 542 delegateless_work_ = true;
313 return false; 543 return false;
314 } 544 }
315 545
546 if (instrumentation_)
547 instrumentation_->WorkSourceEntered(delegate_);
548
316 // The NSApplication-based run loop only drains the autorelease pool at each 549 // The NSApplication-based run loop only drains the autorelease pool at each
317 // UI event (NSEvent). The autorelease pool is not drained for each 550 // UI event (NSEvent). The autorelease pool is not drained for each
318 // CFRunLoopSource target that's run. Use a local pool for any autoreleased 551 // CFRunLoopSource target that's run. Use a local pool for any autoreleased
319 // objects if the app is not currently handling a UI event to ensure they're 552 // objects if the app is not currently handling a UI event to ensure they're
320 // released promptly even in the absence of UI events. 553 // released promptly even in the absence of UI events.
321 MessagePumpScopedAutoreleasePool autorelease_pool(this); 554 MessagePumpScopedAutoreleasePool autorelease_pool(this);
322 555
323 // Call DoWork and DoDelayedWork once, and if something was done, arrange to 556 // Call DoWork and DoDelayedWork once, and if something was done, arrange to
324 // come back here again as long as the loop is still running. 557 // come back here again as long as the loop is still running.
325 bool did_work = delegate_->DoWork(); 558 bool did_work = delegate_->DoWork();
(...skipping 19 matching lines...) Expand all
345 // running. 578 // running.
346 resignal_work_source = true; 579 resignal_work_source = true;
347 } 580 }
348 } 581 }
349 } 582 }
350 583
351 if (resignal_work_source) { 584 if (resignal_work_source) {
352 CFRunLoopSourceSignal(work_source_); 585 CFRunLoopSourceSignal(work_source_);
353 } 586 }
354 587
588 if (instrumentation_)
589 instrumentation_->WorkSourceExited();
590
355 return resignal_work_source; 591 return resignal_work_source;
356 } 592 }
357 593
358 // Called from the run loop. 594 // Called from the run loop.
359 // static 595 // static
360 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { 596 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) {
361 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 597 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
362 self->RunIdleWork(); 598 self->RunIdleWork();
363 } 599 }
364 600
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 // nesting-deferred work in case any work was deferred because nested work 665 // nesting-deferred work in case any work was deferred because nested work
430 // was disallowed. 666 // was disallowed.
431 if (deepest_nesting_level_ > nesting_level_) { 667 if (deepest_nesting_level_ > nesting_level_) {
432 deepest_nesting_level_ = nesting_level_; 668 deepest_nesting_level_ = nesting_level_;
433 CFRunLoopSourceSignal(nesting_deferred_work_source_); 669 CFRunLoopSourceSignal(nesting_deferred_work_source_);
434 } 670 }
435 } 671 }
436 672
437 // Called from the run loop. 673 // Called from the run loop.
438 // static 674 // static
439 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, 675 void MessagePumpCFRunLoopBase::StartOrEndWaitObserver(
440 CFRunLoopActivity activity, 676 CFRunLoopObserverRef observer,
441 void* info) { 677 CFRunLoopActivity activity,
678 void* info) {
442 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 679 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
443 680
681 if (activity == kCFRunLoopAfterWaiting) {
682 if (self->instrumentation_)
683 self->instrumentation_->WaitingFinished();
684 return;
685 }
686
444 // Attempt to do some idle work before going to sleep. 687 // Attempt to do some idle work before going to sleep.
445 self->RunIdleWork(); 688 self->RunIdleWork();
446 689
447 // The run loop is about to go to sleep. If any of the work done since it 690 // The run loop is about to go to sleep. If any of the work done since it
448 // started or woke up resulted in a nested run loop running, 691 // started or woke up resulted in a nested run loop running,
449 // nesting-deferred work may have accumulated. Schedule it for processing 692 // nesting-deferred work may have accumulated. Schedule it for processing
450 // if appropriate. 693 // if appropriate.
451 self->MaybeScheduleNestingDeferredWork(); 694 self->MaybeScheduleNestingDeferredWork();
695
696 if (self->instrumentation_)
697 self->instrumentation_->WaitingStarted();
452 } 698 }
453 699
454 // Called from the run loop. 700 // Called from the run loop.
455 // static 701 // static
456 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer, 702 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer,
457 CFRunLoopActivity activity, 703 CFRunLoopActivity activity,
458 void* info) { 704 void* info) {
459 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 705 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
460 706
461 // The run loop has reached the top of the loop and is about to begin 707 // The run loop has reached the top of the loop and is about to begin
462 // processing sources. If the last iteration of the loop at this nesting 708 // processing sources. If the last iteration of the loop at this nesting
463 // level did not sleep or exit, nesting-deferred work may have accumulated 709 // level did not sleep or exit, nesting-deferred work may have accumulated
464 // if a nested loop ran. Schedule nesting-deferred work for processing if 710 // if a nested loop ran. Schedule nesting-deferred work for processing if
465 // appropriate. 711 // appropriate.
466 self->MaybeScheduleNestingDeferredWork(); 712 self->MaybeScheduleNestingDeferredWork();
467 } 713 }
468 714
469 // Called from the run loop. 715 // Called from the run loop.
470 // static 716 // static
471 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, 717 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer,
472 CFRunLoopActivity activity, 718 CFRunLoopActivity activity,
473 void* info) { 719 void* info) {
474 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 720 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
475 721
476 switch (activity) { 722 switch (activity) {
477 case kCFRunLoopEntry: 723 case kCFRunLoopEntry:
724 if (self->instrumentation_)
725 self->instrumentation_->LoopEntered();
726
478 ++self->nesting_level_; 727 ++self->nesting_level_;
479 if (self->nesting_level_ > self->deepest_nesting_level_) { 728 if (self->nesting_level_ > self->deepest_nesting_level_) {
480 self->deepest_nesting_level_ = self->nesting_level_; 729 self->deepest_nesting_level_ = self->nesting_level_;
481 } 730 }
482 break; 731 break;
483 732
484 case kCFRunLoopExit: 733 case kCFRunLoopExit:
485 // Not all run loops go to sleep. If a run loop is stopped before it 734 // Not all run loops go to sleep. If a run loop is stopped before it
486 // goes to sleep due to a CFRunLoopStop call, or if the timeout passed 735 // goes to sleep due to a CFRunLoopStop call, or if the timeout passed
487 // to CFRunLoopRunInMode expires, the run loop may proceed directly from 736 // to CFRunLoopRunInMode expires, the run loop may proceed directly from
488 // handling sources to exiting without any sleep. This most commonly 737 // handling sources to exiting without any sleep. This most commonly
489 // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it 738 // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it
490 // to make a single pass through the loop and exit without sleep. Some 739 // to make a single pass through the loop and exit without sleep. Some
491 // native loops use CFRunLoop in this way. Because PreWaitObserver will 740 // native loops use CFRunLoop in this way. Because StartOrEndWaitObserver
492 // not be called in these case, MaybeScheduleNestingDeferredWork needs 741 // will not be called in these case, MaybeScheduleNestingDeferredWork
493 // to be called here, as the run loop exits. 742 // needs to be called here, as the run loop exits.
494 // 743 //
495 // MaybeScheduleNestingDeferredWork consults self->nesting_level_ 744 // MaybeScheduleNestingDeferredWork consults self->nesting_level_
496 // to determine whether to schedule nesting-deferred work. It expects 745 // to determine whether to schedule nesting-deferred work. It expects
497 // the nesting level to be set to the depth of the loop that is going 746 // the nesting level to be set to the depth of the loop that is going
498 // to sleep or exiting. It must be called before decrementing the 747 // to sleep or exiting. It must be called before decrementing the
499 // value so that the value still corresponds to the level of the exiting 748 // value so that the value still corresponds to the level of the exiting
500 // loop. 749 // loop.
501 self->MaybeScheduleNestingDeferredWork(); 750 self->MaybeScheduleNestingDeferredWork();
502 --self->nesting_level_; 751 --self->nesting_level_;
752
753 if (self->instrumentation_)
754 self->instrumentation_->LoopExited();
503 break; 755 break;
504 756
505 default: 757 default:
506 break; 758 break;
507 } 759 }
508 760
509 self->EnterExitRunLoop(activity); 761 self->EnterExitRunLoop(activity);
510 } 762 }
511 763
512 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default 764 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 run_loop_ = new RunLoop(); 874 run_loop_ = new RunLoop();
623 CHECK(run_loop_->BeforeRun()); 875 CHECK(run_loop_->BeforeRun());
624 SetDelegate(delegate); 876 SetDelegate(delegate);
625 } 877 }
626 878
627 #else 879 #else
628 880
629 MessagePumpNSApplication::MessagePumpNSApplication() 881 MessagePumpNSApplication::MessagePumpNSApplication()
630 : keep_running_(true), 882 : keep_running_(true),
631 running_own_loop_(false) { 883 running_own_loop_(false) {
884 EnableInstrumentation();
632 } 885 }
633 886
634 MessagePumpNSApplication::~MessagePumpNSApplication() {} 887 MessagePumpNSApplication::~MessagePumpNSApplication() {}
635 888
636 void MessagePumpNSApplication::DoRun(Delegate* delegate) { 889 void MessagePumpNSApplication::DoRun(Delegate* delegate) {
890 if (instrumentation_)
891 instrumentation_->StartIfNeeded();
892
637 bool last_running_own_loop_ = running_own_loop_; 893 bool last_running_own_loop_ = running_own_loop_;
638 894
639 // NSApp must be initialized by calling: 895 // NSApp must be initialized by calling:
640 // [{some class which implements CrAppProtocol} sharedApplication] 896 // [{some class which implements CrAppProtocol} sharedApplication]
641 // Most likely candidates are CrApplication or BrowserCrApplication. 897 // Most likely candidates are CrApplication or BrowserCrApplication.
642 // These can be initialized from C++ code by calling 898 // These can be initialized from C++ code by calling
643 // RegisterCrApp() or RegisterBrowserCrApp(). 899 // RegisterCrApp() or RegisterBrowserCrApp().
644 CHECK(NSApp); 900 CHECK(NSApp);
645 901
646 if (![NSApp isRunning]) { 902 if (![NSApp isRunning]) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 [NSApplication sharedApplication]; 1024 [NSApplication sharedApplication];
769 g_not_using_cr_app = true; 1025 g_not_using_cr_app = true;
770 return new MessagePumpNSApplication; 1026 return new MessagePumpNSApplication;
771 #endif 1027 #endif
772 } 1028 }
773 1029
774 return new MessagePumpNSRunLoop; 1030 return new MessagePumpNSRunLoop;
775 } 1031 }
776 1032
777 } // namespace base 1033 } // namespace base
OLDNEW
« no previous file with comments | « base/message_loop/message_pump_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698