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

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: iOS compile 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
« 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
11 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
12 #include "base/run_loop.h" 14 #include "base/run_loop.h"
15 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h" 16 #include "base/time/time.h"
17 #include "base/timer/timer.h"
14 18
15 #if !defined(OS_IOS) 19 #if !defined(OS_IOS)
16 #import <AppKit/AppKit.h> 20 #import <AppKit/AppKit.h>
17 #endif // !defined(OS_IOS) 21 #endif // !defined(OS_IOS)
18 22
19 namespace { 23 namespace {
20 24
21 void NoOp(void* info) { 25 void NoOp(void* info) {
22 } 26 }
23 27
(...skipping 20 matching lines...) Expand all
44 } 48 }
45 ~MessagePumpScopedAutoreleasePool() { 49 ~MessagePumpScopedAutoreleasePool() {
46 [pool_ drain]; 50 [pool_ drain];
47 } 51 }
48 52
49 private: 53 private:
50 NSAutoreleasePool* pool_; 54 NSAutoreleasePool* pool_;
51 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); 55 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool);
52 }; 56 };
53 57
58 // This class is used to instrument the MessagePump to gather various timing
59 // data about when the underlying run loop is entered, when it is waiting, and
60 // when it is servicing its delegate.
61 //
62 // The metrics are gathered as UMA-tracked histograms. To gather the data over
63 // time, sampling is used, such that a new histogram is created for each metric
64 // every |sampling_interval| for |sampling_duration|. After sampling is
65 // complete, this class deletes itself.
66 class MessagePumpInstrumentation {
67 public:
68 // Creates an instrument for the MessagePump on the current thread. Every
69 // |sampling_interval|, a new histogram will be created to track the metrics
70 // over time. After |sampling_duration|, this will delete itself, causing the
71 // WeakPtr to go NULL.
72 static WeakPtr<MessagePumpInstrumentation> Create(
73 const TimeDelta& sampling_interval,
74 const TimeDelta& sampling_duration) {
75 MessagePumpInstrumentation* instrument =
76 new MessagePumpInstrumentation(sampling_interval, sampling_duration);
77 return instrument->weak_ptr_factory_.GetWeakPtr();
78 }
79
80 // Starts the timer that runs the sampling instrumentation. Can be called
81 // multiple times as a noop.
82 void StartIfNeeded() {
83 if (timer_.IsRunning())
84 return;
85 timer_.Start(FROM_HERE, sampling_interval_,
86 base::Bind(&MessagePumpInstrumentation::TimerFired,
87 weak_ptr_factory_.GetWeakPtr()));
88 }
89
90 // Used to track kCFRunLoopEntry.
91 void LoopEntered() {
92 loop_run_times_.push(TimeTicks::Now());
93 }
94
95 // Used to track kCFRunLoopExit.
96 void LoopExited() {
97 TimeDelta duration = TimeTicks::Now() - loop_run_times_.top();
98 loop_run_times_.pop();
99 GetHistogram(LOOP_CYCLE)->AddTime(duration);
100 }
101
102 // Used to track kCFRunLoopBeforeWaiting.
103 void WaitingStarted() {
104 loop_wait_times_.push(TimeTicks::Now());
105 }
106
107 // Used to track kCFRunLoopAfterWaiting.
108 void WaitingFinished() {
109 TimeDelta duration = TimeTicks::Now() - loop_wait_times_.top();
110 loop_wait_times_.pop();
111 GetHistogram(LOOP_WAIT)->AddTime(duration);
112 }
113
114 // Used to track when the MessagePump will invoke its |delegate|.
115 void WorkSourceEntered(MessagePump::Delegate* delegate) {
116 work_source_times_.push(TimeTicks::Now());
117 if (delegate) {
118 size_t queue_size;
119 TimeDelta queuing_delay;
120 delegate->GetQueueingInformation(&queue_size, &queuing_delay);
121 GetHistogram(QUEUE_SIZE)->Add(queue_size);
122 GetHistogram(QUEUE_DELAY)->AddTime(queuing_delay);
123 }
124 }
125
126 // Used to track the completion of servicing the MessagePump::Delegate.
127 void WorkSourceExited() {
128 TimeDelta duration = TimeTicks::Now() - work_source_times_.top();
129 work_source_times_.pop();
130 GetHistogram(WORK_SOURCE)->AddTime(duration);
131 }
132
133 private:
134 enum HistogramEvent {
135 // Time-based histograms:
136 LOOP_CYCLE, // LoopEntered/LoopExited
137 LOOP_WAIT, // WaitingStarted/WaitingEnded
138 WORK_SOURCE, // WorkSourceExited
139 QUEUE_DELAY, // WorkSourceEntered
140
141 // Value-based histograms:
142 QUEUE_SIZE, // WorkSourceEntered
143
144 HISTOGRAM_EVENT_MAX,
145 };
146
147 MessagePumpInstrumentation(const TimeDelta& sampling_interval,
148 const TimeDelta& sampling_duration)
149 : weak_ptr_factory_(this),
150 sampling_interval_(sampling_interval),
151 sampling_duration_(sampling_duration),
152 sample_count_(0),
153 timer_(true, true) {
154 const char kHistogramName[] = "MessagePumpMac.%s.SampleMs.%lld";
155
156 // Create all the histogram objects that will be used for sampling.
157 for (TimeDelta i; i < sampling_duration_; i += sampling_interval_) {
158 int64 sample = i.InMilliseconds();
159
160 // Generate the time-based histograms.
161 for (HistogramEvent j = LOOP_CYCLE; j < QUEUE_SIZE; ++j) {
Mark Mentovai 2013/08/20 22:44:34 There’s no indication in the enum above that QUEUE
Robert Sesek 2013/08/22 17:49:15 "Solved" with a comment. Fixing this with an in-be
162 std::string name = StringPrintf(kHistogramName, NameForEnum(j), sample);
163 histograms_[j].push_back(
164 Histogram::FactoryTimeGet(name, TimeDelta::FromMilliseconds(1),
165 sampling_interval_, 50,
166 HistogramBase::kUmaTargetedHistogramFlag));
167 }
168
169 // Generate the value-based histograms.
170 for (HistogramEvent j = QUEUE_SIZE; j < HISTOGRAM_EVENT_MAX; ++j) {
171 std::string name = StringPrintf(kHistogramName, NameForEnum(j), sample);
172 histograms_[j].push_back(
173 Histogram::FactoryGet(name, 1, 10000, 50,
174 HistogramBase::kUmaTargetedHistogramFlag));
175 }
176 }
Mark Mentovai 2013/08/20 22:44:34 That was only 75 histograms.
Robert Sesek 2013/08/22 17:49:15 I'll leave it to jar@ to comment on the implicatio
jar (doing other things) 2013/08/22 23:03:39 I'm not convinced that all these histogtrams are u
177 }
178
179 const char* NameForEnum(HistogramEvent event) {
180 switch (event) {
181 case LOOP_CYCLE: return "LoopCycle";
182 case LOOP_WAIT: return "Waiting";
183 case WORK_SOURCE: return "WorkSource";
184 case QUEUE_DELAY: return "QueueingDelay";
185 case QUEUE_SIZE: return "QueueSize";
186 case HISTOGRAM_EVENT_MAX:
Mark Mentovai 2013/08/20 22:44:34 This line is not needed. (Some compiler with lots
Robert Sesek 2013/08/22 17:49:15 Done.
187 default:
188 NOTREACHED();
189 return NULL;
190 }
191 }
192
193 // Called when |sampling_interval| has elapsed.
194 void TimerFired() {
195 ++sample_count_;
196
197 if (sampling_interval_ * sample_count_ >= sampling_duration_) {
198 timer_.Stop();
199 delete this;
200 }
201 }
202
203 HistogramBase* GetHistogram(HistogramEvent event) {
204 return histograms_[event][sample_count_];
205 }
206
207 // Vends the pointer to the Create()er.
208 WeakPtrFactory<MessagePumpInstrumentation> weak_ptr_factory_;
209
210 // The interval and duration of the sampling, as well as the number of
211 // times the timer has fired.
212 TimeDelta sampling_interval_;
213 TimeDelta sampling_duration_;
214 size_t sample_count_;
215
216 // The timer that invokes TimerFired() to advance the |sample_count_|.
217 Timer timer_;
Mark Mentovai 2013/08/20 22:44:34 …this is running on a Timer. And the timers are di
Robert Sesek 2013/08/22 17:49:15 Sigh, I know.
218
219 // The two-dimensional array of histograms. The first dimension is the
220 // HistogramEvent type. The second is for the sampling intervals.
221 std::vector<HistogramBase*> histograms_[HISTOGRAM_EVENT_MAX];
222
223 // MessagePump activations can be nested. Use a stack for each of the
224 // possibly reentrant HistogramEvent types to properly balance and calculate
225 // the timing information.
226 std::stack<TimeTicks> loop_run_times_;
227 std::stack<TimeTicks> loop_wait_times_;
228 std::stack<TimeTicks> work_source_times_;
229
230 DISALLOW_COPY_AND_ASSIGN(MessagePumpInstrumentation);
231 };
232
54 // Must be called on the run loop thread. 233 // Must be called on the run loop thread.
55 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() 234 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
56 : delegate_(NULL), 235 : delegate_(NULL),
57 delayed_work_fire_time_(kCFTimeIntervalMax), 236 delayed_work_fire_time_(kCFTimeIntervalMax),
58 nesting_level_(0), 237 nesting_level_(0),
59 run_nesting_level_(0), 238 run_nesting_level_(0),
60 deepest_nesting_level_(0), 239 deepest_nesting_level_(0),
61 delegateless_work_(false), 240 delegateless_work_(false),
62 delegateless_idle_work_(false) { 241 delegateless_idle_work_(false) {
63 run_loop_ = CFRunLoopGetCurrent(); 242 run_loop_ = CFRunLoopGetCurrent();
(...skipping 30 matching lines...) Expand all
94 source_context.perform = RunNestingDeferredWorkSource; 273 source_context.perform = RunNestingDeferredWorkSource;
95 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator 274 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
96 0, // priority 275 0, // priority
97 &source_context); 276 &source_context);
98 CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_, 277 CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_,
99 kCFRunLoopCommonModes); 278 kCFRunLoopCommonModes);
100 279
101 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); 280 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext();
102 observer_context.info = this; 281 observer_context.info = this;
103 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator 282 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator
104 kCFRunLoopBeforeWaiting, 283 kCFRunLoopBeforeWaiting |
284 kCFRunLoopAfterWaiting,
105 true, // repeat 285 true, // repeat
106 0, // priority 286 0, // priority
107 PreWaitObserver, 287 PreWaitObserver,
Mark Mentovai 2013/08/20 22:44:34 Either your new code is temporary (and you should
Robert Sesek 2013/08/22 17:49:15 Done.
108 &observer_context); 288 &observer_context);
109 CFRunLoopAddObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes); 289 CFRunLoopAddObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes);
110 290
111 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator 291 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator
112 kCFRunLoopBeforeSources, 292 kCFRunLoopBeforeSources,
113 true, // repeat 293 true, // repeat
114 0, // priority 294 0, // priority
115 PreSourceObserver, 295 PreSourceObserver,
116 &observer_context); 296 &observer_context);
117 CFRunLoopAddObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes); 297 CFRunLoopAddObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 CFRunLoopSourceSignal(work_source_); 366 CFRunLoopSourceSignal(work_source_);
187 delegateless_work_ = false; 367 delegateless_work_ = false;
188 } 368 }
189 if (delegateless_idle_work_) { 369 if (delegateless_idle_work_) {
190 CFRunLoopSourceSignal(idle_work_source_); 370 CFRunLoopSourceSignal(idle_work_source_);
191 delegateless_idle_work_ = false; 371 delegateless_idle_work_ = false;
192 } 372 }
193 } 373 }
194 } 374 }
195 375
376 void MessagePumpCFRunLoopBase::EnableInstrumentation() {
377 instrumentation_ = MessagePumpInstrumentation::Create(
378 TimeDelta::FromSeconds(1), TimeDelta::FromSeconds(15));
379 }
380
196 // May be called on any thread. 381 // May be called on any thread.
197 void MessagePumpCFRunLoopBase::ScheduleWork() { 382 void MessagePumpCFRunLoopBase::ScheduleWork() {
198 CFRunLoopSourceSignal(work_source_); 383 CFRunLoopSourceSignal(work_source_);
199 CFRunLoopWakeUp(run_loop_); 384 CFRunLoopWakeUp(run_loop_);
200 } 385 }
201 386
202 // Must be called on the run loop thread. 387 // Must be called on the run loop thread.
203 void MessagePumpCFRunLoopBase::ScheduleDelayedWork( 388 void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
204 const TimeTicks& delayed_work_time) { 389 const TimeTicks& delayed_work_time) {
205 TimeDelta delta = delayed_work_time - TimeTicks::Now(); 390 TimeDelta delta = delayed_work_time - TimeTicks::Now();
(...skipping 27 matching lines...) Expand all
233 // Called by MessagePumpCFRunLoopBase::RunWorkSource. 418 // Called by MessagePumpCFRunLoopBase::RunWorkSource.
234 bool MessagePumpCFRunLoopBase::RunWork() { 419 bool MessagePumpCFRunLoopBase::RunWork() {
235 if (!delegate_) { 420 if (!delegate_) {
236 // This point can be reached with a NULL delegate_ if Run is not on the 421 // 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 422 // stack but foreign code is spinning the CFRunLoop. Arrange to come back
238 // here when a delegate is available. 423 // here when a delegate is available.
239 delegateless_work_ = true; 424 delegateless_work_ = true;
240 return false; 425 return false;
241 } 426 }
242 427
428 if (instrumentation_)
429 instrumentation_->WorkSourceEntered(delegate_);
430
243 // The NSApplication-based run loop only drains the autorelease pool at each 431 // The NSApplication-based run loop only drains the autorelease pool at each
244 // UI event (NSEvent). The autorelease pool is not drained for each 432 // UI event (NSEvent). The autorelease pool is not drained for each
245 // CFRunLoopSource target that's run. Use a local pool for any autoreleased 433 // 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 434 // 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. 435 // released promptly even in the absence of UI events.
248 MessagePumpScopedAutoreleasePool autorelease_pool(this); 436 MessagePumpScopedAutoreleasePool autorelease_pool(this);
249 437
250 // Call DoWork and DoDelayedWork once, and if something was done, arrange to 438 // 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. 439 // come back here again as long as the loop is still running.
252 bool did_work = delegate_->DoWork(); 440 bool did_work = delegate_->DoWork();
(...skipping 19 matching lines...) Expand all
272 // running. 460 // running.
273 resignal_work_source = true; 461 resignal_work_source = true;
274 } 462 }
275 } 463 }
276 } 464 }
277 465
278 if (resignal_work_source) { 466 if (resignal_work_source) {
279 CFRunLoopSourceSignal(work_source_); 467 CFRunLoopSourceSignal(work_source_);
280 } 468 }
281 469
470 if (instrumentation_)
471 instrumentation_->WorkSourceExited();
472
282 return resignal_work_source; 473 return resignal_work_source;
283 } 474 }
284 475
285 // Called from the run loop. 476 // Called from the run loop.
286 // static 477 // static
287 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { 478 void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) {
288 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 479 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
289 self->RunIdleWork(); 480 self->RunIdleWork();
290 } 481 }
291 482
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 } 552 }
362 } 553 }
363 554
364 // Called from the run loop. 555 // Called from the run loop.
365 // static 556 // static
366 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, 557 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer,
367 CFRunLoopActivity activity, 558 CFRunLoopActivity activity,
368 void* info) { 559 void* info) {
369 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 560 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
370 561
562 if (activity == kCFRunLoopAfterWaiting) {
563 if (self->instrumentation_)
564 self->instrumentation_->WaitingFinished();
565 return;
566 }
567
371 // Attempt to do some idle work before going to sleep. 568 // Attempt to do some idle work before going to sleep.
372 self->RunIdleWork(); 569 self->RunIdleWork();
373 570
374 // The run loop is about to go to sleep. If any of the work done since it 571 // 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, 572 // started or woke up resulted in a nested run loop running,
376 // nesting-deferred work may have accumulated. Schedule it for processing 573 // nesting-deferred work may have accumulated. Schedule it for processing
377 // if appropriate. 574 // if appropriate.
378 self->MaybeScheduleNestingDeferredWork(); 575 self->MaybeScheduleNestingDeferredWork();
576
577 if (self->instrumentation_)
578 self->instrumentation_->WaitingStarted();
379 } 579 }
380 580
381 // Called from the run loop. 581 // Called from the run loop.
382 // static 582 // static
383 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer, 583 void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer,
384 CFRunLoopActivity activity, 584 CFRunLoopActivity activity,
385 void* info) { 585 void* info) {
386 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 586 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
387 587
388 // The run loop has reached the top of the loop and is about to begin 588 // 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 589 // 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 590 // 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 591 // if a nested loop ran. Schedule nesting-deferred work for processing if
392 // appropriate. 592 // appropriate.
393 self->MaybeScheduleNestingDeferredWork(); 593 self->MaybeScheduleNestingDeferredWork();
394 } 594 }
395 595
396 // Called from the run loop. 596 // Called from the run loop.
397 // static 597 // static
398 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, 598 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer,
399 CFRunLoopActivity activity, 599 CFRunLoopActivity activity,
400 void* info) { 600 void* info) {
401 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 601 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
402 602
403 switch (activity) { 603 switch (activity) {
404 case kCFRunLoopEntry: 604 case kCFRunLoopEntry:
605 if (self->instrumentation_)
606 self->instrumentation_->LoopEntered();
607
405 ++self->nesting_level_; 608 ++self->nesting_level_;
406 if (self->nesting_level_ > self->deepest_nesting_level_) { 609 if (self->nesting_level_ > self->deepest_nesting_level_) {
407 self->deepest_nesting_level_ = self->nesting_level_; 610 self->deepest_nesting_level_ = self->nesting_level_;
408 } 611 }
409 break; 612 break;
410 613
411 case kCFRunLoopExit: 614 case kCFRunLoopExit:
412 // Not all run loops go to sleep. If a run loop is stopped before it 615 // 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 616 // goes to sleep due to a CFRunLoopStop call, or if the timeout passed
414 // to CFRunLoopRunInMode expires, the run loop may proceed directly from 617 // to CFRunLoopRunInMode expires, the run loop may proceed directly from
415 // handling sources to exiting without any sleep. This most commonly 618 // handling sources to exiting without any sleep. This most commonly
416 // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it 619 // 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 620 // to make a single pass through the loop and exit without sleep. Some
418 // native loops use CFRunLoop in this way. Because PreWaitObserver will 621 // native loops use CFRunLoop in this way. Because PreWaitObserver will
419 // not be called in these case, MaybeScheduleNestingDeferredWork needs 622 // not be called in these case, MaybeScheduleNestingDeferredWork needs
420 // to be called here, as the run loop exits. 623 // to be called here, as the run loop exits.
421 // 624 //
422 // MaybeScheduleNestingDeferredWork consults self->nesting_level_ 625 // MaybeScheduleNestingDeferredWork consults self->nesting_level_
423 // to determine whether to schedule nesting-deferred work. It expects 626 // 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 627 // 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 628 // 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 629 // value so that the value still corresponds to the level of the exiting
427 // loop. 630 // loop.
428 self->MaybeScheduleNestingDeferredWork(); 631 self->MaybeScheduleNestingDeferredWork();
429 --self->nesting_level_; 632 --self->nesting_level_;
633
634 if (self->instrumentation_)
635 self->instrumentation_->LoopExited();
430 break; 636 break;
431 637
432 default: 638 default:
433 break; 639 break;
434 } 640 }
435 641
436 self->EnterExitRunLoop(activity); 642 self->EnterExitRunLoop(activity);
437 } 643 }
438 644
439 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default 645 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 run_loop_ = new RunLoop(); 755 run_loop_ = new RunLoop();
550 CHECK(run_loop_->BeforeRun()); 756 CHECK(run_loop_->BeforeRun());
551 SetDelegate(delegate); 757 SetDelegate(delegate);
552 } 758 }
553 759
554 #else 760 #else
555 761
556 MessagePumpNSApplication::MessagePumpNSApplication() 762 MessagePumpNSApplication::MessagePumpNSApplication()
557 : keep_running_(true), 763 : keep_running_(true),
558 running_own_loop_(false) { 764 running_own_loop_(false) {
765 EnableInstrumentation();
559 } 766 }
560 767
561 MessagePumpNSApplication::~MessagePumpNSApplication() {} 768 MessagePumpNSApplication::~MessagePumpNSApplication() {}
562 769
563 void MessagePumpNSApplication::DoRun(Delegate* delegate) { 770 void MessagePumpNSApplication::DoRun(Delegate* delegate) {
771 if (instrumentation_)
772 instrumentation_->StartIfNeeded();
773
564 bool last_running_own_loop_ = running_own_loop_; 774 bool last_running_own_loop_ = running_own_loop_;
565 775
566 // NSApp must be initialized by calling: 776 // NSApp must be initialized by calling:
567 // [{some class which implements CrAppProtocol} sharedApplication] 777 // [{some class which implements CrAppProtocol} sharedApplication]
568 // Most likely candidates are CrApplication or BrowserCrApplication. 778 // Most likely candidates are CrApplication or BrowserCrApplication.
569 // These can be initialized from C++ code by calling 779 // These can be initialized from C++ code by calling
570 // RegisterCrApp() or RegisterBrowserCrApp(). 780 // RegisterCrApp() or RegisterBrowserCrApp().
571 CHECK(NSApp); 781 CHECK(NSApp);
572 782
573 if (![NSApp isRunning]) { 783 if (![NSApp isRunning]) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 [NSApplication sharedApplication]; 905 [NSApplication sharedApplication];
696 g_not_using_cr_app = true; 906 g_not_using_cr_app = true;
697 return new MessagePumpNSApplication; 907 return new MessagePumpNSApplication;
698 #endif 908 #endif
699 } 909 }
700 910
701 return new MessagePumpNSRunLoop; 911 return new MessagePumpNSRunLoop;
702 } 912 }
703 913
704 } // namespace base 914 } // 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