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

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

Issue 22911026: Add instrumentation to the MessagePumpMac family of classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add caveat Created 7 years, 3 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 #import <Foundation/Foundation.h> 7 #import <Foundation/Foundation.h>
8 8
9 #include <limits> 9 #include <limits>
10 #include <stack>
10 11
12 #include "base/format_macros.h"
11 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/mac/scoped_cftyperef.h"
15 #include "base/metrics/histogram.h"
12 #include "base/run_loop.h" 16 #include "base/run_loop.h"
17 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h" 18 #include "base/time/time.h"
14 19
15 #if !defined(OS_IOS) 20 #if !defined(OS_IOS)
16 #import <AppKit/AppKit.h> 21 #import <AppKit/AppKit.h>
17 #endif // !defined(OS_IOS) 22 #endif // !defined(OS_IOS)
18 23
19 namespace { 24 namespace {
20 25
21 void NoOp(void* info) { 26 void NoOp(void* info) {
22 } 27 }
(...skipping 21 matching lines...) Expand all
44 } 49 }
45 ~MessagePumpScopedAutoreleasePool() { 50 ~MessagePumpScopedAutoreleasePool() {
46 [pool_ drain]; 51 [pool_ drain];
47 } 52 }
48 53
49 private: 54 private:
50 NSAutoreleasePool* pool_; 55 NSAutoreleasePool* pool_;
51 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); 56 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool);
52 }; 57 };
53 58
59 // This class is used to instrument the MessagePump to gather various timing
60 // data about when the underlying run loop is entered, when it is waiting, and
61 // when it is servicing its delegate.
62 //
63 // The metrics are gathered as UMA-tracked histograms. To gather the data over
64 // time, sampling is used, such that a new histogram is created for each metric
65 // every |sampling_interval| for |sampling_duration|. After sampling is
66 // complete, this class deletes itself.
67 class MessagePumpInstrumentation {
68 public:
69 // Creates an instrument for the MessagePump on the current thread. Every
70 // |sampling_interval|, a new histogram will be created to track the metrics
71 // over time. After |sampling_duration|, this will delete itself, causing the
72 // WeakPtr to go NULL.
73 static WeakPtr<MessagePumpInstrumentation> Create(
74 const TimeDelta& sampling_interval,
75 const TimeDelta& sampling_duration) {
76 MessagePumpInstrumentation* instrument =
77 new MessagePumpInstrumentation(sampling_interval, sampling_duration);
78 return instrument->weak_ptr_factory_.GetWeakPtr();
79 }
80
81 // Starts the timer that runs the sampling instrumentation. Can be called
82 // multiple times as a noop.
83 void StartIfNeeded() {
84 if (timer_)
85 return;
86
87 sampling_start_time_ = generation_start_time_ = TimeTicks::Now();
88
89 CFRunLoopTimerContext timer_context = { .info = this };
90 timer_.reset(CFRunLoopTimerCreate(
91 NULL, // allocator
92 (Time::Now() + sampling_interval_).ToCFAbsoluteTime(),
93 sampling_interval_.InSecondsF(),
94 0, // flags
95 0, // order
96 &MessagePumpInstrumentation::TimerFired,
97 &timer_context));
98 CFRunLoopAddTimer(CFRunLoopGetCurrent(),
99 timer_,
100 kCFRunLoopCommonModes);
101 }
102
103 // Used to track kCFRunLoopEntry.
104 void LoopEntered() {
105 loop_run_times_.push(TimeTicks::Now());
106 }
107
108 // Used to track kCFRunLoopExit.
109 void LoopExited() {
110 TimeDelta duration = TimeTicks::Now() - loop_run_times_.top();
111 loop_run_times_.pop();
112 GetHistogram(LOOP_CYCLE)->AddTime(duration);
113 }
114
115 // Used to track kCFRunLoopBeforeWaiting.
116 void WaitingStarted() {
117 loop_wait_times_.push(TimeTicks::Now());
118 }
119
120 // Used to track kCFRunLoopAfterWaiting.
121 void WaitingFinished() {
122 TimeDelta duration = TimeTicks::Now() - loop_wait_times_.top();
123 loop_wait_times_.pop();
124 GetHistogram(LOOP_WAIT)->AddTime(duration);
125 }
126
127 // Used to track when the MessagePump will invoke its |delegate|.
128 void WorkSourceEntered(MessagePump::Delegate* delegate) {
129 work_source_times_.push(TimeTicks::Now());
130 if (delegate) {
131 size_t queue_size;
132 TimeDelta queuing_delay;
133 delegate->GetQueueingInformation(&queue_size, &queuing_delay);
134 GetHistogram(QUEUE_SIZE)->Add(queue_size);
135 GetHistogram(QUEUE_DELAY)->AddTime(queuing_delay);
136 }
137 }
138
139 // Used to track the completion of servicing the MessagePump::Delegate.
140 void WorkSourceExited() {
141 TimeDelta duration = TimeTicks::Now() - work_source_times_.top();
142 work_source_times_.pop();
143 GetHistogram(WORK_SOURCE)->AddTime(duration);
144 }
145
146 private:
147 enum HistogramEvent {
148 // Time-based histograms:
149 LOOP_CYCLE, // LoopEntered/LoopExited
150 LOOP_WAIT, // WaitingStarted/WaitingEnded
151 WORK_SOURCE, // WorkSourceExited
152 QUEUE_DELAY, // WorkSourceEntered
153
154 // Value-based histograms:
155 // NOTE: Do not add value-based histograms before this event, only after.
156 QUEUE_SIZE, // WorkSourceEntered
157
158 HISTOGRAM_EVENT_MAX,
159 };
160
161 MessagePumpInstrumentation(const TimeDelta& sampling_interval,
162 const TimeDelta& sampling_duration)
163 : weak_ptr_factory_(this),
164 sampling_interval_(sampling_interval),
165 sampling_duration_(sampling_duration),
166 sample_generation_(0) {
167 // Create all the histogram objects that will be used for sampling.
168 const char kHistogramName[] = "MessagePumpMac.%s.SampleMs.%" PRId64;
169 for (TimeDelta i; i < sampling_duration_; i += sampling_interval_) {
170 int64 sample = i.InMilliseconds();
171
172 // Generate the time-based histograms.
173 for (int j = LOOP_CYCLE; j < QUEUE_SIZE; ++j) {
174 std::string name = StringPrintf(kHistogramName,
175 NameForEnum(static_cast<HistogramEvent>(j)), sample);
176 histograms_[j].push_back(
177 Histogram::FactoryTimeGet(name, TimeDelta::FromMilliseconds(1),
178 sampling_interval_, 50,
179 HistogramBase::kUmaTargetedHistogramFlag));
180 }
181
182 // Generate the value-based histograms.
183 for (int j = QUEUE_SIZE; j < HISTOGRAM_EVENT_MAX; ++j) {
184 std::string name = StringPrintf(kHistogramName,
185 NameForEnum(static_cast<HistogramEvent>(j)), sample);
186 histograms_[j].push_back(
187 Histogram::FactoryGet(name, 1, 10000, 50,
188 HistogramBase::kUmaTargetedHistogramFlag));
189 }
190 }
191 }
192
193 ~MessagePumpInstrumentation() {
194 if (timer_)
195 CFRunLoopTimerInvalidate(timer_);
196 }
197
198 const char* NameForEnum(HistogramEvent event) {
199 switch (event) {
200 case LOOP_CYCLE: return "LoopCycle";
201 case LOOP_WAIT: return "Waiting";
202 case WORK_SOURCE: return "WorkSource";
203 case QUEUE_DELAY: return "QueueingDelay";
204 case QUEUE_SIZE: return "QueueSize";
205 default:
206 NOTREACHED();
207 return NULL;
208 }
209 }
210
211 static void TimerFired(CFRunLoopTimerRef timer, void* context) {
212 static_cast<MessagePumpInstrumentation*>(context)->TimerFired();
213 }
214
215 // Called by the run loop when the sampling_interval_ has elapsed. Advances
216 // the sample_generation_, which controls into which histogram data is
217 // recorded, while recording and accounting for timer skew. Will delete this
218 // object after |sampling_duration_| has elapsed.
219 void TimerFired() {
220 TimeTicks now = TimeTicks::Now();
221 TimeDelta delta = now - generation_start_time_;
222
223 // The timer fired, so advance the generation by at least one.
224 ++sample_generation_;
225
226 // To account for large timer skew/drift, advance the generation by any
227 // more completed intervals.
228 for (TimeDelta skew_advance = delta - sampling_interval_;
229 skew_advance >= sampling_interval_;
230 skew_advance -= sampling_interval_) {
231 ++sample_generation_;
232 }
233
234 generation_start_time_ = now;
235 if (now >= sampling_start_time_ + sampling_duration_)
236 delete this;
237 }
238
239 HistogramBase* GetHistogram(HistogramEvent event) {
240 DCHECK_LT(sample_generation_, histograms_[event].size());
241 return histograms_[event][sample_generation_];
242 }
243
244 // Vends the pointer to the Create()or.
245 WeakPtrFactory<MessagePumpInstrumentation> weak_ptr_factory_;
246
247 // The interval and duration of the sampling.
248 TimeDelta sampling_interval_;
249 TimeDelta sampling_duration_;
250
251 // The time at which sampling started.
252 TimeTicks sampling_start_time_;
253
254 // The timer that advances the sample_generation_ and sets the
255 // generation_start_time_ for the current sample interval.
256 base::ScopedCFTypeRef<CFRunLoopTimerRef> timer_;
257
258 // The two-dimensional array of histograms. The first dimension is the
259 // HistogramEvent type. The second is for the sampling intervals.
260 std::vector<HistogramBase*> histograms_[HISTOGRAM_EVENT_MAX];
261
262 // The index in the second dimension of histograms_, which controls in which
263 // sampled histogram events are recorded.
264 size_t sample_generation_;
265
266 // The last time at which the timer fired. This is used to track timer skew
267 // (i.e. it did not fire on time) and properly account for it when advancing
268 // samle_generation_.
269 TimeTicks generation_start_time_;
270
271 // MessagePump activations can be nested. Use a stack for each of the
272 // possibly reentrant HistogramEvent types to properly balance and calculate
273 // the timing information.
274 std::stack<TimeTicks> loop_run_times_;
275 std::stack<TimeTicks> loop_wait_times_;
276 std::stack<TimeTicks> work_source_times_;
277
278 DISALLOW_COPY_AND_ASSIGN(MessagePumpInstrumentation);
279 };
280
54 // Must be called on the run loop thread. 281 // Must be called on the run loop thread.
55 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() 282 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
56 : delegate_(NULL), 283 : delegate_(NULL),
57 delayed_work_fire_time_(kCFTimeIntervalMax), 284 delayed_work_fire_time_(kCFTimeIntervalMax),
58 nesting_level_(0), 285 nesting_level_(0),
59 run_nesting_level_(0), 286 run_nesting_level_(0),
60 deepest_nesting_level_(0), 287 deepest_nesting_level_(0),
61 delegateless_work_(false), 288 delegateless_work_(false),
62 delegateless_idle_work_(false) { 289 delegateless_idle_work_(false) {
63 run_loop_ = CFRunLoopGetCurrent(); 290 run_loop_ = CFRunLoopGetCurrent();
(...skipping 30 matching lines...) Expand all
94 source_context.perform = RunNestingDeferredWorkSource; 321 source_context.perform = RunNestingDeferredWorkSource;
95 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator 322 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
96 0, // priority 323 0, // priority
97 &source_context); 324 &source_context);
98 CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_, 325 CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_,
99 kCFRunLoopCommonModes); 326 kCFRunLoopCommonModes);
100 327
101 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); 328 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext();
102 observer_context.info = this; 329 observer_context.info = this;
103 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator 330 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator
104 kCFRunLoopBeforeWaiting, 331 kCFRunLoopBeforeWaiting |
332 kCFRunLoopAfterWaiting,
105 true, // repeat 333 true, // repeat
106 0, // priority 334 0, // priority
107 PreWaitObserver, 335 StartOrEndWaitObserver,
108 &observer_context); 336 &observer_context);
109 CFRunLoopAddObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes); 337 CFRunLoopAddObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes);
110 338
111 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator 339 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator
112 kCFRunLoopBeforeSources, 340 kCFRunLoopBeforeSources,
113 true, // repeat 341 true, // repeat
114 0, // priority 342 0, // priority
115 PreSourceObserver, 343 PreSourceObserver,
116 &observer_context); 344 &observer_context);
117 CFRunLoopAddObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes); 345 CFRunLoopAddObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 CFRunLoopSourceSignal(work_source_); 414 CFRunLoopSourceSignal(work_source_);
187 delegateless_work_ = false; 415 delegateless_work_ = false;
188 } 416 }
189 if (delegateless_idle_work_) { 417 if (delegateless_idle_work_) {
190 CFRunLoopSourceSignal(idle_work_source_); 418 CFRunLoopSourceSignal(idle_work_source_);
191 delegateless_idle_work_ = false; 419 delegateless_idle_work_ = false;
192 } 420 }
193 } 421 }
194 } 422 }
195 423
424 void MessagePumpCFRunLoopBase::EnableInstrumentation() {
425 instrumentation_ = MessagePumpInstrumentation::Create(
426 TimeDelta::FromSeconds(1), TimeDelta::FromSeconds(15));
427 }
428
196 // May be called on any thread. 429 // May be called on any thread.
197 void MessagePumpCFRunLoopBase::ScheduleWork() { 430 void MessagePumpCFRunLoopBase::ScheduleWork() {
198 CFRunLoopSourceSignal(work_source_); 431 CFRunLoopSourceSignal(work_source_);
199 CFRunLoopWakeUp(run_loop_); 432 CFRunLoopWakeUp(run_loop_);
200 } 433 }
201 434
202 // Must be called on the run loop thread. 435 // Must be called on the run loop thread.
203 void MessagePumpCFRunLoopBase::ScheduleDelayedWork( 436 void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
204 const TimeTicks& delayed_work_time) { 437 const TimeTicks& delayed_work_time) {
205 TimeDelta delta = delayed_work_time - TimeTicks::Now(); 438 TimeDelta delta = delayed_work_time - TimeTicks::Now();
(...skipping 27 matching lines...) Expand all
233 // Called by MessagePumpCFRunLoopBase::RunWorkSource. 466 // Called by MessagePumpCFRunLoopBase::RunWorkSource.
234 bool MessagePumpCFRunLoopBase::RunWork() { 467 bool MessagePumpCFRunLoopBase::RunWork() {
235 if (!delegate_) { 468 if (!delegate_) {
236 // This point can be reached with a NULL delegate_ if Run is not on the 469 // This point can be reached with a NULL delegate_ if Run is not on the
237 // stack but foreign code is spinning the CFRunLoop. Arrange to come back 470 // stack but foreign code is spinning the CFRunLoop. Arrange to come back
238 // here when a delegate is available. 471 // here when a delegate is available.
239 delegateless_work_ = true; 472 delegateless_work_ = true;
240 return false; 473 return false;
241 } 474 }
242 475
476 if (instrumentation_)
477 instrumentation_->WorkSourceEntered(delegate_);
478
243 // The NSApplication-based run loop only drains the autorelease pool at each 479 // The NSApplication-based run loop only drains the autorelease pool at each
244 // UI event (NSEvent). The autorelease pool is not drained for each 480 // UI event (NSEvent). The autorelease pool is not drained for each
245 // CFRunLoopSource target that's run. Use a local pool for any autoreleased 481 // CFRunLoopSource target that's run. Use a local pool for any autoreleased
246 // objects if the app is not currently handling a UI event to ensure they're 482 // objects if the app is not currently handling a UI event to ensure they're
247 // released promptly even in the absence of UI events. 483 // released promptly even in the absence of UI events.
248 MessagePumpScopedAutoreleasePool autorelease_pool(this); 484 MessagePumpScopedAutoreleasePool autorelease_pool(this);
249 485
250 // Call DoWork and DoDelayedWork once, and if something was done, arrange to 486 // Call DoWork and DoDelayedWork once, and if something was done, arrange to
251 // come back here again as long as the loop is still running. 487 // come back here again as long as the loop is still running.
252 bool did_work = delegate_->DoWork(); 488 bool did_work = delegate_->DoWork();
(...skipping 19 matching lines...) Expand all
272 // running. 508 // running.
273 resignal_work_source = true; 509 resignal_work_source = true;
274 } 510 }
275 } 511 }
276 } 512 }
277 513
278 if (resignal_work_source) { 514 if (resignal_work_source) {
279 CFRunLoopSourceSignal(work_source_); 515 CFRunLoopSourceSignal(work_source_);
280 } 516 }
281 517
518 if (instrumentation_)
519 instrumentation_->WorkSourceExited();
520
282 return resignal_work_source; 521 return resignal_work_source;
283 } 522 }
284 523
285 // Called from the run loop. 524 // Called from the run loop.
286 // static 525 // static
287 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { 526 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) {
288 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 527 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
289 self->RunIdleWork(); 528 self->RunIdleWork();
290 } 529 }
291 530
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 // nesting-deferred work in case any work was deferred because nested work 595 // nesting-deferred work in case any work was deferred because nested work
357 // was disallowed. 596 // was disallowed.
358 if (deepest_nesting_level_ > nesting_level_) { 597 if (deepest_nesting_level_ > nesting_level_) {
359 deepest_nesting_level_ = nesting_level_; 598 deepest_nesting_level_ = nesting_level_;
360 CFRunLoopSourceSignal(nesting_deferred_work_source_); 599 CFRunLoopSourceSignal(nesting_deferred_work_source_);
361 } 600 }
362 } 601 }
363 602
364 // Called from the run loop. 603 // Called from the run loop.
365 // static 604 // static
366 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, 605 void MessagePumpCFRunLoopBase::StartOrEndWaitObserver(
367 CFRunLoopActivity activity, 606 CFRunLoopObserverRef observer,
368 void* info) { 607 CFRunLoopActivity activity,
608 void* info) {
369 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 609 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
370 610
611 if (activity == kCFRunLoopAfterWaiting) {
612 if (self->instrumentation_)
613 self->instrumentation_->WaitingFinished();
614 return;
615 }
616
371 // Attempt to do some idle work before going to sleep. 617 // Attempt to do some idle work before going to sleep.
372 self->RunIdleWork(); 618 self->RunIdleWork();
373 619
374 // The run loop is about to go to sleep. If any of the work done since it 620 // The run loop is about to go to sleep. If any of the work done since it
375 // started or woke up resulted in a nested run loop running, 621 // started or woke up resulted in a nested run loop running,
376 // nesting-deferred work may have accumulated. Schedule it for processing 622 // nesting-deferred work may have accumulated. Schedule it for processing
377 // if appropriate. 623 // if appropriate.
378 self->MaybeScheduleNestingDeferredWork(); 624 self->MaybeScheduleNestingDeferredWork();
625
626 if (self->instrumentation_)
627 self->instrumentation_->WaitingStarted();
379 } 628 }
380 629
381 // Called from the run loop. 630 // Called from the run loop.
382 // static 631 // static
383 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer, 632 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer,
384 CFRunLoopActivity activity, 633 CFRunLoopActivity activity,
385 void* info) { 634 void* info) {
386 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 635 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
387 636
388 // The run loop has reached the top of the loop and is about to begin 637 // The run loop has reached the top of the loop and is about to begin
389 // processing sources. If the last iteration of the loop at this nesting 638 // processing sources. If the last iteration of the loop at this nesting
390 // level did not sleep or exit, nesting-deferred work may have accumulated 639 // level did not sleep or exit, nesting-deferred work may have accumulated
391 // if a nested loop ran. Schedule nesting-deferred work for processing if 640 // if a nested loop ran. Schedule nesting-deferred work for processing if
392 // appropriate. 641 // appropriate.
393 self->MaybeScheduleNestingDeferredWork(); 642 self->MaybeScheduleNestingDeferredWork();
394 } 643 }
395 644
396 // Called from the run loop. 645 // Called from the run loop.
397 // static 646 // static
398 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, 647 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer,
399 CFRunLoopActivity activity, 648 CFRunLoopActivity activity,
400 void* info) { 649 void* info) {
401 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 650 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
402 651
403 switch (activity) { 652 switch (activity) {
404 case kCFRunLoopEntry: 653 case kCFRunLoopEntry:
654 if (self->instrumentation_)
655 self->instrumentation_->LoopEntered();
656
405 ++self->nesting_level_; 657 ++self->nesting_level_;
406 if (self->nesting_level_ > self->deepest_nesting_level_) { 658 if (self->nesting_level_ > self->deepest_nesting_level_) {
407 self->deepest_nesting_level_ = self->nesting_level_; 659 self->deepest_nesting_level_ = self->nesting_level_;
408 } 660 }
409 break; 661 break;
410 662
411 case kCFRunLoopExit: 663 case kCFRunLoopExit:
412 // Not all run loops go to sleep. If a run loop is stopped before it 664 // Not all run loops go to sleep. If a run loop is stopped before it
413 // goes to sleep due to a CFRunLoopStop call, or if the timeout passed 665 // goes to sleep due to a CFRunLoopStop call, or if the timeout passed
414 // to CFRunLoopRunInMode expires, the run loop may proceed directly from 666 // to CFRunLoopRunInMode expires, the run loop may proceed directly from
415 // handling sources to exiting without any sleep. This most commonly 667 // handling sources to exiting without any sleep. This most commonly
416 // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it 668 // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it
417 // to make a single pass through the loop and exit without sleep. Some 669 // to make a single pass through the loop and exit without sleep. Some
418 // native loops use CFRunLoop in this way. Because PreWaitObserver will 670 // native loops use CFRunLoop in this way. Because StartOrEndWaitObserver
419 // not be called in these case, MaybeScheduleNestingDeferredWork needs 671 // will not be called in these case, MaybeScheduleNestingDeferredWork
420 // to be called here, as the run loop exits. 672 // needs to be called here, as the run loop exits.
421 // 673 //
422 // MaybeScheduleNestingDeferredWork consults self->nesting_level_ 674 // MaybeScheduleNestingDeferredWork consults self->nesting_level_
423 // to determine whether to schedule nesting-deferred work. It expects 675 // to determine whether to schedule nesting-deferred work. It expects
424 // the nesting level to be set to the depth of the loop that is going 676 // the nesting level to be set to the depth of the loop that is going
425 // to sleep or exiting. It must be called before decrementing the 677 // to sleep or exiting. It must be called before decrementing the
426 // value so that the value still corresponds to the level of the exiting 678 // value so that the value still corresponds to the level of the exiting
427 // loop. 679 // loop.
428 self->MaybeScheduleNestingDeferredWork(); 680 self->MaybeScheduleNestingDeferredWork();
429 --self->nesting_level_; 681 --self->nesting_level_;
682
683 if (self->instrumentation_)
684 self->instrumentation_->LoopExited();
430 break; 685 break;
431 686
432 default: 687 default:
433 break; 688 break;
434 } 689 }
435 690
436 self->EnterExitRunLoop(activity); 691 self->EnterExitRunLoop(activity);
437 } 692 }
438 693
439 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default 694 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 run_loop_ = new RunLoop(); 804 run_loop_ = new RunLoop();
550 CHECK(run_loop_->BeforeRun()); 805 CHECK(run_loop_->BeforeRun());
551 SetDelegate(delegate); 806 SetDelegate(delegate);
552 } 807 }
553 808
554 #else 809 #else
555 810
556 MessagePumpNSApplication::MessagePumpNSApplication() 811 MessagePumpNSApplication::MessagePumpNSApplication()
557 : keep_running_(true), 812 : keep_running_(true),
558 running_own_loop_(false) { 813 running_own_loop_(false) {
814 EnableInstrumentation();
559 } 815 }
560 816
561 MessagePumpNSApplication::~MessagePumpNSApplication() {} 817 MessagePumpNSApplication::~MessagePumpNSApplication() {}
562 818
563 void MessagePumpNSApplication::DoRun(Delegate* delegate) { 819 void MessagePumpNSApplication::DoRun(Delegate* delegate) {
820 if (instrumentation_)
821 instrumentation_->StartIfNeeded();
822
564 bool last_running_own_loop_ = running_own_loop_; 823 bool last_running_own_loop_ = running_own_loop_;
565 824
566 // NSApp must be initialized by calling: 825 // NSApp must be initialized by calling:
567 // [{some class which implements CrAppProtocol} sharedApplication] 826 // [{some class which implements CrAppProtocol} sharedApplication]
568 // Most likely candidates are CrApplication or BrowserCrApplication. 827 // Most likely candidates are CrApplication or BrowserCrApplication.
569 // These can be initialized from C++ code by calling 828 // These can be initialized from C++ code by calling
570 // RegisterCrApp() or RegisterBrowserCrApp(). 829 // RegisterCrApp() or RegisterBrowserCrApp().
571 CHECK(NSApp); 830 CHECK(NSApp);
572 831
573 if (![NSApp isRunning]) { 832 if (![NSApp isRunning]) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 [NSApplication sharedApplication]; 954 [NSApplication sharedApplication];
696 g_not_using_cr_app = true; 955 g_not_using_cr_app = true;
697 return new MessagePumpNSApplication; 956 return new MessagePumpNSApplication;
698 #endif 957 #endif
699 } 958 }
700 959
701 return new MessagePumpNSRunLoop; 960 return new MessagePumpNSRunLoop;
702 } 961 }
703 962
704 } // namespace base 963 } // 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