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

Side by Side Diff: base/message_loop/message_loop.cc

Issue 1011683002: Lazily initialize MessageLoop for faster thread startup (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: StartAndWait -> StartAndWaitForTesting Created 5 years, 8 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 #include "base/message_loop/message_loop.h" 5 #include "base/message_loop/message_loop.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 #elif defined(OS_POSIX) 93 #elif defined(OS_POSIX)
94 typedef MessagePumpLibevent MessagePumpForIO; 94 typedef MessagePumpLibevent MessagePumpForIO;
95 #endif 95 #endif
96 96
97 #if !defined(OS_NACL_SFI) 97 #if !defined(OS_NACL_SFI)
98 MessagePumpForIO* ToPumpIO(MessagePump* pump) { 98 MessagePumpForIO* ToPumpIO(MessagePump* pump) {
99 return static_cast<MessagePumpForIO*>(pump); 99 return static_cast<MessagePumpForIO*>(pump);
100 } 100 }
101 #endif // !defined(OS_NACL_SFI) 101 #endif // !defined(OS_NACL_SFI)
102 102
103 MessageLoop::Type GetMessageLoopType(const MessageLoop::InitOptions& options) {
104 if (options.message_pump_factory.is_null())
danakj 2015/04/24 20:54:39 this was a little bit of work to parse in my head
kinuko 2015/04/27 16:36:04 (This code is now gone)
105 return options.message_loop_type;
106 return MessageLoop::TYPE_CUSTOM;
107 }
108
103 } // namespace 109 } // namespace
104 110
105 //------------------------------------------------------------------------------ 111 //------------------------------------------------------------------------------
106 112
113 MessageLoop::InitOptions::InitOptions()
114 : message_loop_type(MessageLoop::TYPE_DEFAULT),
115 timer_slack(TIMER_SLACK_NONE) {
116 }
117
118 MessageLoop::InitOptions::~InitOptions() {
119 }
120
121 //------------------------------------------------------------------------------
122
107 MessageLoop::TaskObserver::TaskObserver() { 123 MessageLoop::TaskObserver::TaskObserver() {
108 } 124 }
109 125
110 MessageLoop::TaskObserver::~TaskObserver() { 126 MessageLoop::TaskObserver::~TaskObserver() {
111 } 127 }
112 128
113 MessageLoop::DestructionObserver::~DestructionObserver() { 129 MessageLoop::DestructionObserver::~DestructionObserver() {
114 } 130 }
115 131
116 //------------------------------------------------------------------------------ 132 //------------------------------------------------------------------------------
117 133
134 MessageLoop::MessageLoop(const InitOptions& options)
135 : type_(GetMessageLoopType(options)),
136 #if defined(OS_WIN)
137 pending_high_res_tasks_(0),
138 in_high_res_mode_(false),
139 #endif
140 nestable_tasks_allowed_(true),
141 #if defined(OS_WIN)
142 os_modal_loop_(false),
143 #endif // OS_WIN
144 init_options_(new InitOptions(options)),
Nico 2015/04/24 21:31:15 Maybe this should be passed in as scoped_ptr? That
kinuko 2015/04/27 16:36:04 (This struct is now gone)
145 message_histogram_(NULL),
146 run_loop_(NULL),
147 incoming_task_queue_(new internal::IncomingTaskQueue(this)),
148 message_loop_proxy_(
149 new internal::MessageLoopProxyImpl(incoming_task_queue_)) {
150 }
151
118 MessageLoop::MessageLoop(Type type) 152 MessageLoop::MessageLoop(Type type)
119 : type_(type), 153 : type_(type),
120 #if defined(OS_WIN) 154 #if defined(OS_WIN)
121 pending_high_res_tasks_(0), 155 pending_high_res_tasks_(0),
122 in_high_res_mode_(false), 156 in_high_res_mode_(false),
123 #endif 157 #endif
124 nestable_tasks_allowed_(true), 158 nestable_tasks_allowed_(true),
125 #if defined(OS_WIN) 159 #if defined(OS_WIN)
126 os_modal_loop_(false), 160 os_modal_loop_(false),
127 #endif // OS_WIN 161 #endif // OS_WIN
128 message_histogram_(NULL), 162 message_histogram_(NULL),
129 run_loop_(NULL) { 163 run_loop_(NULL),
164 incoming_task_queue_(new internal::IncomingTaskQueue(this)),
165 message_loop_proxy_(
166 new internal::MessageLoopProxyImpl(incoming_task_queue_)) {
130 Init(); 167 Init();
danakj 2015/04/24 20:54:39 it'd be nice if these other constructors set up an
Nico 2015/04/24 21:31:15 It feels strange that one constructor doesn't crea
kinuko 2015/04/27 16:36:04 Done.
131
132 pump_ = CreateMessagePumpForType(type).Pass(); 168 pump_ = CreateMessagePumpForType(type).Pass();
133 } 169 }
134 170
135 MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump) 171 MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump)
136 : pump_(pump.Pass()), 172 : pump_(pump.Pass()),
137 type_(TYPE_CUSTOM), 173 type_(TYPE_CUSTOM),
138 #if defined(OS_WIN) 174 #if defined(OS_WIN)
139 pending_high_res_tasks_(0), 175 pending_high_res_tasks_(0),
140 in_high_res_mode_(false), 176 in_high_res_mode_(false),
141 #endif 177 #endif
142 nestable_tasks_allowed_(true), 178 nestable_tasks_allowed_(true),
143 #if defined(OS_WIN) 179 #if defined(OS_WIN)
144 os_modal_loop_(false), 180 os_modal_loop_(false),
145 #endif // OS_WIN 181 #endif // OS_WIN
146 message_histogram_(NULL), 182 message_histogram_(NULL),
147 run_loop_(NULL) { 183 run_loop_(NULL),
184 incoming_task_queue_(new internal::IncomingTaskQueue(this)),
185 message_loop_proxy_(
186 new internal::MessageLoopProxyImpl(incoming_task_queue_)) {
148 DCHECK(pump_.get()); 187 DCHECK(pump_.get());
149 Init(); 188 Init();
150 } 189 }
151 190
152 MessageLoop::~MessageLoop() { 191 MessageLoop::~MessageLoop() {
192 if (init_options_) {
193 // This message loop is destructed before we call Init.
danakj 2015/04/24 20:54:39 Why do you do this early out path, what are you tr
kinuko 2015/04/27 16:36:04 The code below is not really meaningful when this
194 DCHECK(current() == NULL);
195 DCHECK(incoming_task_queue_->empty());
196 DCHECK(!pump_);
197 DCHECK(!destruction_observers_.might_have_observers());
198 incoming_task_queue_->WillDestroyCurrentMessageLoop();
199 return;
200 }
201
153 DCHECK_EQ(this, current()); 202 DCHECK_EQ(this, current());
154 203
155 // iOS just attaches to the loop, it doesn't Run it. 204 // iOS just attaches to the loop, it doesn't Run it.
156 // TODO(stuartmorgan): Consider wiring up a Detach(). 205 // TODO(stuartmorgan): Consider wiring up a Detach().
157 #if !defined(OS_IOS) 206 #if !defined(OS_IOS)
158 DCHECK(!run_loop_); 207 DCHECK(!run_loop_);
159 #endif 208 #endif
160 209
161 #if defined(OS_WIN) 210 #if defined(OS_WIN)
162 if (in_high_res_mode_) 211 if (in_high_res_mode_)
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 302
254 #if defined(OS_ANDROID) 303 #if defined(OS_ANDROID)
255 if (type == MessageLoop::TYPE_JAVA) 304 if (type == MessageLoop::TYPE_JAVA)
256 return scoped_ptr<MessagePump>(new MessagePumpForUI()); 305 return scoped_ptr<MessagePump>(new MessagePumpForUI());
257 #endif 306 #endif
258 307
259 DCHECK_EQ(MessageLoop::TYPE_DEFAULT, type); 308 DCHECK_EQ(MessageLoop::TYPE_DEFAULT, type);
260 return MESSAGE_PUMP_DEFAULT; 309 return MESSAGE_PUMP_DEFAULT;
261 } 310 }
262 311
312 void MessageLoop::Init() {
313 if (init_options_) {
314 DCHECK(!pump_);
315 if (!init_options_->message_pump_factory.is_null())
316 pump_ = init_options_->message_pump_factory.Run();
317 else
318 pump_ = CreateMessagePumpForType(init_options_->message_loop_type);
319 SetTimerSlack(init_options_->timer_slack);
320 init_options_.reset();
321 }
322
323 DCHECK(!current()) << "should only have one message loop per thread";
324 lazy_tls_ptr.Pointer()->Set(this);
325
326 incoming_task_queue_->StartScheduling();
327 message_loop_proxy_->Init();
328 thread_task_runner_handle_.reset(
329 new ThreadTaskRunnerHandle(message_loop_proxy_));
330 }
331
263 void MessageLoop::AddDestructionObserver( 332 void MessageLoop::AddDestructionObserver(
264 DestructionObserver* destruction_observer) { 333 DestructionObserver* destruction_observer) {
265 DCHECK_EQ(this, current()); 334 DCHECK_EQ(this, current());
266 destruction_observers_.AddObserver(destruction_observer); 335 destruction_observers_.AddObserver(destruction_observer);
267 } 336 }
268 337
269 void MessageLoop::RemoveDestructionObserver( 338 void MessageLoop::RemoveDestructionObserver(
270 DestructionObserver* destruction_observer) { 339 DestructionObserver* destruction_observer) {
271 DCHECK_EQ(this, current()); 340 DCHECK_EQ(this, current());
272 destruction_observers_.RemoveObserver(destruction_observer); 341 destruction_observers_.RemoveObserver(destruction_observer);
(...skipping 19 matching lines...) Expand all
292 } 361 }
293 362
294 void MessageLoop::PostNonNestableDelayedTask( 363 void MessageLoop::PostNonNestableDelayedTask(
295 const tracked_objects::Location& from_here, 364 const tracked_objects::Location& from_here,
296 const Closure& task, 365 const Closure& task,
297 TimeDelta delay) { 366 TimeDelta delay) {
298 message_loop_proxy_->PostNonNestableDelayedTask(from_here, task, delay); 367 message_loop_proxy_->PostNonNestableDelayedTask(from_here, task, delay);
299 } 368 }
300 369
301 void MessageLoop::Run() { 370 void MessageLoop::Run() {
371 DCHECK(!init_options_);
302 RunLoop run_loop; 372 RunLoop run_loop;
303 run_loop.Run(); 373 run_loop.Run();
304 } 374 }
305 375
306 void MessageLoop::RunUntilIdle() { 376 void MessageLoop::RunUntilIdle() {
377 DCHECK(!init_options_);
307 RunLoop run_loop; 378 RunLoop run_loop;
308 run_loop.RunUntilIdle(); 379 run_loop.RunUntilIdle();
309 } 380 }
310 381
311 void MessageLoop::QuitWhenIdle() { 382 void MessageLoop::QuitWhenIdle() {
312 DCHECK_EQ(this, current()); 383 DCHECK_EQ(this, current());
313 if (run_loop_) { 384 if (run_loop_) {
314 run_loop_->quit_when_idle_received_ = true; 385 run_loop_->quit_when_idle_received_ = true;
315 } else { 386 } else {
316 NOTREACHED() << "Must be inside Run to call Quit"; 387 NOTREACHED() << "Must be inside Run to call Quit";
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 } 447 }
377 448
378 bool MessageLoop::IsIdleForTesting() { 449 bool MessageLoop::IsIdleForTesting() {
379 // We only check the imcoming queue|, since we don't want to lock the work 450 // We only check the imcoming queue|, since we don't want to lock the work
380 // queue. 451 // queue.
381 return incoming_task_queue_->IsIdleForTesting(); 452 return incoming_task_queue_->IsIdleForTesting();
382 } 453 }
383 454
384 //------------------------------------------------------------------------------ 455 //------------------------------------------------------------------------------
385 456
386 void MessageLoop::Init() { 457 void MessageLoop::ScheduleWork() {
387 DCHECK(!current()) << "should only have one message loop per thread"; 458 pump_->ScheduleWork();
388 lazy_tls_ptr.Pointer()->Set(this);
389
390 incoming_task_queue_ = new internal::IncomingTaskQueue(this);
391 message_loop_proxy_ =
392 new internal::MessageLoopProxyImpl(incoming_task_queue_);
393 thread_task_runner_handle_.reset(
394 new ThreadTaskRunnerHandle(message_loop_proxy_));
395 } 459 }
396 460
397 void MessageLoop::RunHandler() { 461 void MessageLoop::RunHandler() {
398 DCHECK_EQ(this, current()); 462 DCHECK_EQ(this, current());
399 463
400 StartHistogrammer(); 464 StartHistogrammer();
401 465
402 #if defined(OS_WIN) 466 #if defined(OS_WIN)
403 if (run_loop_->dispatcher_ && type() == TYPE_UI) { 467 if (run_loop_->dispatcher_ && type() == TYPE_UI) {
404 static_cast<MessagePumpForUI*>(pump_.get())-> 468 static_cast<MessagePumpForUI*>(pump_.get())->
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 if (work_queue_.empty()) { 569 if (work_queue_.empty()) {
506 #if defined(OS_WIN) 570 #if defined(OS_WIN)
507 pending_high_res_tasks_ += 571 pending_high_res_tasks_ +=
508 incoming_task_queue_->ReloadWorkQueue(&work_queue_); 572 incoming_task_queue_->ReloadWorkQueue(&work_queue_);
509 #else 573 #else
510 incoming_task_queue_->ReloadWorkQueue(&work_queue_); 574 incoming_task_queue_->ReloadWorkQueue(&work_queue_);
511 #endif 575 #endif
512 } 576 }
513 } 577 }
514 578
515 void MessageLoop::ScheduleWork() {
516 pump_->ScheduleWork();
517 }
518
519 //------------------------------------------------------------------------------ 579 //------------------------------------------------------------------------------
520 // Method and data for histogramming events and actions taken by each instance 580 // Method and data for histogramming events and actions taken by each instance
521 // on each thread. 581 // on each thread.
522 582
523 void MessageLoop::StartHistogrammer() { 583 void MessageLoop::StartHistogrammer() {
524 #if !defined(OS_NACL) // NaCl build has no metrics code. 584 #if !defined(OS_NACL) // NaCl build has no metrics code.
525 if (enable_histogrammer_ && !message_histogram_ 585 if (enable_histogrammer_ && !message_histogram_
526 && StatisticsRecorder::IsActive()) { 586 && StatisticsRecorder::IsActive()) {
527 DCHECK(!thread_name_.empty()); 587 DCHECK(!thread_name_.empty());
528 message_histogram_ = LinearHistogram::FactoryGetWithRangeDescription( 588 message_histogram_ = LinearHistogram::FactoryGetWithRangeDescription(
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 persistent, 771 persistent,
712 mode, 772 mode,
713 controller, 773 controller,
714 delegate); 774 delegate);
715 } 775 }
716 #endif 776 #endif
717 777
718 #endif // !defined(OS_NACL_SFI) 778 #endif // !defined(OS_NACL_SFI)
719 779
720 } // namespace base 780 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698