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

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: Address some comments from jar Created 7 years, 4 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
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 (HistogramEvent j = LOOP_CYCLE; j < QUEUE_SIZE; ++j) {
174 std::string name = StringPrintf(kHistogramName, NameForEnum(j), sample);
175 histograms_[j].push_back(
176 Histogram::FactoryTimeGet(name, TimeDelta::FromMilliseconds(1),
177 sampling_interval_, 50,
178 HistogramBase::kUmaTargetedHistogramFlag));
179 }
180
181 // Generate the value-based histograms.
182 for (HistogramEvent j = QUEUE_SIZE; j < HISTOGRAM_EVENT_MAX; ++j) {
183 std::string name = StringPrintf(kHistogramName, NameForEnum(j), sample);
184 histograms_[j].push_back(
185 Histogram::FactoryGet(name, 1, 10000, 50,
186 HistogramBase::kUmaTargetedHistogramFlag));
187 }
188 }
189 }
190
191 ~MessagePumpInstrumentation() {
192 if (timer_)
193 CFRunLoopTimerInvalidate(timer_);
194 }
195
196 const char* NameForEnum(HistogramEvent event) {
197 switch (event) {
198 case LOOP_CYCLE: return "LoopCycle";
199 case LOOP_WAIT: return "Waiting";
200 case WORK_SOURCE: return "WorkSource";
201 case QUEUE_DELAY: return "QueueingDelay";
202 case QUEUE_SIZE: return "QueueSize";
203 default:
204 NOTREACHED();
205 return NULL;
206 }
207 }
208
209 static void TimerFired(CFRunLoopTimerRef timer, void* context) {
210 static_cast<MessagePumpInstrumentation*>(context)->TimerFired();
211 }
212
213 // Called by the run loop when the sampling_interval_ has elapsed. Advances
214 // the sample_generation_, which controls into which histogram data is
215 // recorded, while recording and accounting for timer skew. Will delete this
216 // object after |sampling_duration_| has elapsed.
217 void TimerFired() {
218 TimeTicks now = TimeTicks::Now();
219 TimeDelta delta = now - generation_start_time_;
220
221 // The timer fired, so advance the generation by at least one.
222 ++sample_generation_;
223
224 // To account for large timer skew/drift, advance the generation by any
225 // more completed intervals.
226 for (TimeDelta skew_advance = delta - sampling_interval_;
227 skew_advance >= sampling_interval_;
228 skew_advance -= sampling_interval_) {
229 ++sample_generation_;
230 }
231
232 generation_start_time_ = now;
233 if (now >= sampling_start_time_ + sampling_duration_)
234 delete this;
235 }
236
237 HistogramBase* GetHistogram(HistogramEvent event) {
238 DCHECK_LT(sample_generation_, histograms_[event].size());
239 return histograms_[event][sample_generation_];
240 }
241
242 // Vends the pointer to the Create()or.
243 WeakPtrFactory<MessagePumpInstrumentation> weak_ptr_factory_;
244
245 // The interval and duration of the sampling.
246 TimeDelta sampling_interval_;
247 TimeDelta sampling_duration_;
248
249 // The time at which sampling started.
250 TimeTicks sampling_start_time_;
251
252 // The timer that advances the sample_generation_ and sets the
253 // generation_start_time_ for the current sample interval.
254 base::ScopedCFTypeRef<CFRunLoopTimerRef> timer_;
255
256 // The two-dimensional array of histograms. The first dimension is the
257 // HistogramEvent type. The second is for the sampling intervals.
258 std::vector<HistogramBase*> histograms_[HISTOGRAM_EVENT_MAX];
259
260 // The index in the second dimension of histograms_, which controls in which
261 // sampled histogram events are recorded.
262 size_t sample_generation_;
263
264 // The last time at which the timer fired. This is used to track timer skew
265 // (i.e. it did not fire on time) and properly account for it when advancing
266 // samle_generation_.
267 TimeTicks generation_start_time_;
268
269 // MessagePump activations can be nested. Use a stack for each of the
270 // possibly reentrant HistogramEvent types to properly balance and calculate
271 // the timing information.
272 std::stack<TimeTicks> loop_run_times_;
273 std::stack<TimeTicks> loop_wait_times_;
274 std::stack<TimeTicks> work_source_times_;
275
276 DISALLOW_COPY_AND_ASSIGN(MessagePumpInstrumentation);
277 };
278
54 // Must be called on the run loop thread. 279 // Must be called on the run loop thread.
55 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() 280 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
56 : delegate_(NULL), 281 : delegate_(NULL),
57 delayed_work_fire_time_(kCFTimeIntervalMax), 282 delayed_work_fire_time_(kCFTimeIntervalMax),
58 nesting_level_(0), 283 nesting_level_(0),
59 run_nesting_level_(0), 284 run_nesting_level_(0),
60 deepest_nesting_level_(0), 285 deepest_nesting_level_(0),
61 delegateless_work_(false), 286 delegateless_work_(false),
62 delegateless_idle_work_(false) { 287 delegateless_idle_work_(false) {
63 run_loop_ = CFRunLoopGetCurrent(); 288 run_loop_ = CFRunLoopGetCurrent();
(...skipping 29 matching lines...) Expand all
93 318
94 source_context.perform = RunNestingDeferredWorkSource; 319 source_context.perform = RunNestingDeferredWorkSource;
95 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator 320 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
96 0, // priority 321 0, // priority
97 &source_context); 322 &source_context);
98 CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_, 323 CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_,
99 kCFRunLoopCommonModes); 324 kCFRunLoopCommonModes);
100 325
101 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); 326 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext();
102 observer_context.info = this; 327 observer_context.info = this;
103 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator 328 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator
jar (doing other things) 2013/08/29 22:15:08 I'm surprised we do this. Adding an observer on a
Robert Sesek 2013/08/30 16:25:07 This observer is added once at the creation of the
jar (doing other things) 2013/09/04 01:20:17 I see... this is a Mac thing... not the generic ta
104 kCFRunLoopBeforeWaiting, 329 kCFRunLoopBeforeWaiting |
330 kCFRunLoopAfterWaiting,
105 true, // repeat 331 true, // repeat
106 0, // priority 332 0, // priority
107 PreWaitObserver, 333 StartOrEndWaitObserver,
108 &observer_context); 334 &observer_context);
109 CFRunLoopAddObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes); 335 CFRunLoopAddObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes);
110 336
111 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator 337 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator
112 kCFRunLoopBeforeSources, 338 kCFRunLoopBeforeSources,
113 true, // repeat 339 true, // repeat
114 0, // priority 340 0, // priority
115 PreSourceObserver, 341 PreSourceObserver,
116 &observer_context); 342 &observer_context);
117 CFRunLoopAddObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes); 343 CFRunLoopAddObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 CFRunLoopSourceSignal(work_source_); 412 CFRunLoopSourceSignal(work_source_);
187 delegateless_work_ = false; 413 delegateless_work_ = false;
188 } 414 }
189 if (delegateless_idle_work_) { 415 if (delegateless_idle_work_) {
190 CFRunLoopSourceSignal(idle_work_source_); 416 CFRunLoopSourceSignal(idle_work_source_);
191 delegateless_idle_work_ = false; 417 delegateless_idle_work_ = false;
192 } 418 }
193 } 419 }
194 } 420 }
195 421
422 void MessagePumpCFRunLoopBase::EnableInstrumentation() {
423 instrumentation_ = MessagePumpInstrumentation::Create(
424 TimeDelta::FromSeconds(1), TimeDelta::FromSeconds(15));
425 }
426
196 // May be called on any thread. 427 // May be called on any thread.
197 void MessagePumpCFRunLoopBase::ScheduleWork() { 428 void MessagePumpCFRunLoopBase::ScheduleWork() {
198 CFRunLoopSourceSignal(work_source_); 429 CFRunLoopSourceSignal(work_source_);
199 CFRunLoopWakeUp(run_loop_); 430 CFRunLoopWakeUp(run_loop_);
200 } 431 }
201 432
202 // Must be called on the run loop thread. 433 // Must be called on the run loop thread.
203 void MessagePumpCFRunLoopBase::ScheduleDelayedWork( 434 void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
204 const TimeTicks& delayed_work_time) { 435 const TimeTicks& delayed_work_time) {
205 TimeDelta delta = delayed_work_time - TimeTicks::Now(); 436 TimeDelta delta = delayed_work_time - TimeTicks::Now();
(...skipping 27 matching lines...) Expand all
233 // Called by MessagePumpCFRunLoopBase::RunWorkSource. 464 // Called by MessagePumpCFRunLoopBase::RunWorkSource.
234 bool MessagePumpCFRunLoopBase::RunWork() { 465 bool MessagePumpCFRunLoopBase::RunWork() {
235 if (!delegate_) { 466 if (!delegate_) {
236 // This point can be reached with a NULL delegate_ if Run is not on the 467 // 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 468 // stack but foreign code is spinning the CFRunLoop. Arrange to come back
238 // here when a delegate is available. 469 // here when a delegate is available.
239 delegateless_work_ = true; 470 delegateless_work_ = true;
240 return false; 471 return false;
241 } 472 }
242 473
474 if (instrumentation_)
475 instrumentation_->WorkSourceEntered(delegate_);
476
243 // The NSApplication-based run loop only drains the autorelease pool at each 477 // The NSApplication-based run loop only drains the autorelease pool at each
244 // UI event (NSEvent). The autorelease pool is not drained for each 478 // UI event (NSEvent). The autorelease pool is not drained for each
245 // CFRunLoopSource target that's run. Use a local pool for any autoreleased 479 // 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 480 // 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. 481 // released promptly even in the absence of UI events.
248 MessagePumpScopedAutoreleasePool autorelease_pool(this); 482 MessagePumpScopedAutoreleasePool autorelease_pool(this);
249 483
250 // Call DoWork and DoDelayedWork once, and if something was done, arrange to 484 // 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. 485 // come back here again as long as the loop is still running.
252 bool did_work = delegate_->DoWork(); 486 bool did_work = delegate_->DoWork();
(...skipping 19 matching lines...) Expand all
272 // running. 506 // running.
273 resignal_work_source = true; 507 resignal_work_source = true;
274 } 508 }
275 } 509 }
276 } 510 }
277 511
278 if (resignal_work_source) { 512 if (resignal_work_source) {
279 CFRunLoopSourceSignal(work_source_); 513 CFRunLoopSourceSignal(work_source_);
280 } 514 }
281 515
516 if (instrumentation_)
517 instrumentation_->WorkSourceExited();
518
282 return resignal_work_source; 519 return resignal_work_source;
283 } 520 }
284 521
285 // Called from the run loop. 522 // Called from the run loop.
286 // static 523 // static
287 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { 524 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) {
288 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 525 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
289 self->RunIdleWork(); 526 self->RunIdleWork();
290 } 527 }
291 528
(...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 593 // nesting-deferred work in case any work was deferred because nested work
357 // was disallowed. 594 // was disallowed.
358 if (deepest_nesting_level_ > nesting_level_) { 595 if (deepest_nesting_level_ > nesting_level_) {
359 deepest_nesting_level_ = nesting_level_; 596 deepest_nesting_level_ = nesting_level_;
360 CFRunLoopSourceSignal(nesting_deferred_work_source_); 597 CFRunLoopSourceSignal(nesting_deferred_work_source_);
361 } 598 }
362 } 599 }
363 600
364 // Called from the run loop. 601 // Called from the run loop.
365 // static 602 // static
366 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, 603 void MessagePumpCFRunLoopBase::StartOrEndWaitObserver(
367 CFRunLoopActivity activity, 604 CFRunLoopObserverRef observer,
368 void* info) { 605 CFRunLoopActivity activity,
606 void* info) {
369 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 607 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
370 608
609 if (activity == kCFRunLoopAfterWaiting) {
610 if (self->instrumentation_)
611 self->instrumentation_->WaitingFinished();
612 return;
613 }
614
371 // Attempt to do some idle work before going to sleep. 615 // Attempt to do some idle work before going to sleep.
372 self->RunIdleWork(); 616 self->RunIdleWork();
373 617
374 // The run loop is about to go to sleep. If any of the work done since it 618 // 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, 619 // started or woke up resulted in a nested run loop running,
376 // nesting-deferred work may have accumulated. Schedule it for processing 620 // nesting-deferred work may have accumulated. Schedule it for processing
377 // if appropriate. 621 // if appropriate.
378 self->MaybeScheduleNestingDeferredWork(); 622 self->MaybeScheduleNestingDeferredWork();
623
624 if (self->instrumentation_)
625 self->instrumentation_->WaitingStarted();
379 } 626 }
380 627
381 // Called from the run loop. 628 // Called from the run loop.
382 // static 629 // static
383 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer, 630 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer,
384 CFRunLoopActivity activity, 631 CFRunLoopActivity activity,
385 void* info) { 632 void* info) {
386 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 633 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
387 634
388 // The run loop has reached the top of the loop and is about to begin 635 // 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 636 // 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 637 // 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 638 // if a nested loop ran. Schedule nesting-deferred work for processing if
392 // appropriate. 639 // appropriate.
393 self->MaybeScheduleNestingDeferredWork(); 640 self->MaybeScheduleNestingDeferredWork();
394 } 641 }
395 642
396 // Called from the run loop. 643 // Called from the run loop.
397 // static 644 // static
398 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, 645 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer,
399 CFRunLoopActivity activity, 646 CFRunLoopActivity activity,
400 void* info) { 647 void* info) {
401 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 648 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
402 649
403 switch (activity) { 650 switch (activity) {
404 case kCFRunLoopEntry: 651 case kCFRunLoopEntry:
652 if (self->instrumentation_)
653 self->instrumentation_->LoopEntered();
654
405 ++self->nesting_level_; 655 ++self->nesting_level_;
406 if (self->nesting_level_ > self->deepest_nesting_level_) { 656 if (self->nesting_level_ > self->deepest_nesting_level_) {
407 self->deepest_nesting_level_ = self->nesting_level_; 657 self->deepest_nesting_level_ = self->nesting_level_;
408 } 658 }
409 break; 659 break;
410 660
411 case kCFRunLoopExit: 661 case kCFRunLoopExit:
412 // Not all run loops go to sleep. If a run loop is stopped before it 662 // 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 663 // goes to sleep due to a CFRunLoopStop call, or if the timeout passed
414 // to CFRunLoopRunInMode expires, the run loop may proceed directly from 664 // to CFRunLoopRunInMode expires, the run loop may proceed directly from
415 // handling sources to exiting without any sleep. This most commonly 665 // handling sources to exiting without any sleep. This most commonly
416 // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it 666 // 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 667 // to make a single pass through the loop and exit without sleep. Some
418 // native loops use CFRunLoop in this way. Because PreWaitObserver will 668 // native loops use CFRunLoop in this way. Because StartOrEndWaitObserver
419 // not be called in these case, MaybeScheduleNestingDeferredWork needs 669 // will not be called in these case, MaybeScheduleNestingDeferredWork
420 // to be called here, as the run loop exits. 670 // needs to be called here, as the run loop exits.
421 // 671 //
422 // MaybeScheduleNestingDeferredWork consults self->nesting_level_ 672 // MaybeScheduleNestingDeferredWork consults self->nesting_level_
423 // to determine whether to schedule nesting-deferred work. It expects 673 // 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 674 // 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 675 // 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 676 // value so that the value still corresponds to the level of the exiting
427 // loop. 677 // loop.
428 self->MaybeScheduleNestingDeferredWork(); 678 self->MaybeScheduleNestingDeferredWork();
429 --self->nesting_level_; 679 --self->nesting_level_;
680
681 if (self->instrumentation_)
682 self->instrumentation_->LoopExited();
430 break; 683 break;
431 684
432 default: 685 default:
433 break; 686 break;
434 } 687 }
435 688
436 self->EnterExitRunLoop(activity); 689 self->EnterExitRunLoop(activity);
437 } 690 }
438 691
439 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default 692 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 run_loop_ = new RunLoop(); 802 run_loop_ = new RunLoop();
550 CHECK(run_loop_->BeforeRun()); 803 CHECK(run_loop_->BeforeRun());
551 SetDelegate(delegate); 804 SetDelegate(delegate);
552 } 805 }
553 806
554 #else 807 #else
555 808
556 MessagePumpNSApplication::MessagePumpNSApplication() 809 MessagePumpNSApplication::MessagePumpNSApplication()
557 : keep_running_(true), 810 : keep_running_(true),
558 running_own_loop_(false) { 811 running_own_loop_(false) {
812 EnableInstrumentation();
559 } 813 }
560 814
561 MessagePumpNSApplication::~MessagePumpNSApplication() {} 815 MessagePumpNSApplication::~MessagePumpNSApplication() {}
562 816
563 void MessagePumpNSApplication::DoRun(Delegate* delegate) { 817 void MessagePumpNSApplication::DoRun(Delegate* delegate) {
818 if (instrumentation_)
819 instrumentation_->StartIfNeeded();
820
564 bool last_running_own_loop_ = running_own_loop_; 821 bool last_running_own_loop_ = running_own_loop_;
565 822
566 // NSApp must be initialized by calling: 823 // NSApp must be initialized by calling:
567 // [{some class which implements CrAppProtocol} sharedApplication] 824 // [{some class which implements CrAppProtocol} sharedApplication]
568 // Most likely candidates are CrApplication or BrowserCrApplication. 825 // Most likely candidates are CrApplication or BrowserCrApplication.
569 // These can be initialized from C++ code by calling 826 // These can be initialized from C++ code by calling
570 // RegisterCrApp() or RegisterBrowserCrApp(). 827 // RegisterCrApp() or RegisterBrowserCrApp().
571 CHECK(NSApp); 828 CHECK(NSApp);
572 829
573 if (![NSApp isRunning]) { 830 if (![NSApp isRunning]) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 [NSApplication sharedApplication]; 952 [NSApplication sharedApplication];
696 g_not_using_cr_app = true; 953 g_not_using_cr_app = true;
697 return new MessagePumpNSApplication; 954 return new MessagePumpNSApplication;
698 #endif 955 #endif
699 } 956 }
700 957
701 return new MessagePumpNSRunLoop; 958 return new MessagePumpNSRunLoop;
702 } 959 }
703 960
704 } // namespace base 961 } // namespace base
OLDNEW
« base/message_loop/message_pump.h ('K') | « 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