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

Side by Side Diff: base/message_pump_win.cc

Issue 3094: As an intermediary step towards having a message pump handling IO through com... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 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_pump_win.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) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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_pump_win.h" 5 #include "base/message_pump_win.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/histogram.h" 9 #include "base/histogram.h"
10 #include "base/win_util.h" 10 #include "base/win_util.h"
(...skipping 17 matching lines...) Expand all
28 // MessagePumpWin public: 28 // MessagePumpWin public:
29 29
30 MessagePumpWin::MessagePumpWin() : have_work_(0), state_(NULL) { 30 MessagePumpWin::MessagePumpWin() : have_work_(0), state_(NULL) {
31 InitMessageWnd(); 31 InitMessageWnd();
32 } 32 }
33 33
34 MessagePumpWin::~MessagePumpWin() { 34 MessagePumpWin::~MessagePumpWin() {
35 DestroyWindow(message_hwnd_); 35 DestroyWindow(message_hwnd_);
36 } 36 }
37 37
38 void MessagePumpWin::WatchObject(HANDLE object, Watcher* watcher) {
39 DCHECK(object);
40 DCHECK_NE(object, INVALID_HANDLE_VALUE);
41
42 std::vector<HANDLE>::iterator it =
43 find(objects_.begin(), objects_.end(), object);
44 if (watcher) {
45 if (it == objects_.end()) {
46 static size_t warning_multiple = 1;
47 if (objects_.size() >= warning_multiple * MAXIMUM_WAIT_OBJECTS / 2) {
48 LOG(INFO) << "More than " << warning_multiple * MAXIMUM_WAIT_OBJECTS / 2
49 << " objects being watched";
50 // This DCHECK() is an artificial limitation, meant to warn us if we
51 // start creating too many objects. It can safely be raised to a higher
52 // level, and the program is designed to handle much larger values.
53 // Before raising this limit, make sure that there is a very good reason
54 // (in your debug testing) to be watching this many objects.
55 DCHECK(2 <= warning_multiple);
56 ++warning_multiple;
57 }
58 objects_.push_back(object);
59 watchers_.push_back(watcher);
60 } else {
61 watchers_[it - objects_.begin()] = watcher;
62 }
63 } else if (it != objects_.end()) {
64 std::vector<HANDLE>::difference_type index = it - objects_.begin();
65 objects_.erase(it);
66 watchers_.erase(watchers_.begin() + index);
67 }
68 }
69
70 void MessagePumpWin::AddObserver(Observer* observer) { 38 void MessagePumpWin::AddObserver(Observer* observer) {
71 observers_.AddObserver(observer); 39 observers_.AddObserver(observer);
72 } 40 }
73 41
74 void MessagePumpWin::RemoveObserver(Observer* observer) { 42 void MessagePumpWin::RemoveObserver(Observer* observer) {
75 observers_.RemoveObserver(observer); 43 observers_.RemoveObserver(observer);
76 } 44 }
77 45
78 void MessagePumpWin::WillProcessMessage(const MSG& msg) { 46 void MessagePumpWin::WillProcessMessage(const MSG& msg) {
79 FOR_EACH_OBSERVER(Observer, observers_, WillProcessMessage(msg)); 47 FOR_EACH_OBSERVER(Observer, observers_, WillProcessMessage(msg));
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 DCHECK(delay_msec >= 0); 137 DCHECK(delay_msec >= 0);
170 if (delay_msec < USER_TIMER_MINIMUM) 138 if (delay_msec < USER_TIMER_MINIMUM)
171 delay_msec = USER_TIMER_MINIMUM; 139 delay_msec = USER_TIMER_MINIMUM;
172 140
173 // Create a WM_TIMER event that will wake us up to check for any pending 141 // Create a WM_TIMER event that will wake us up to check for any pending
174 // timers (in case we are running within a nested, external sub-pump). 142 // timers (in case we are running within a nested, external sub-pump).
175 SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), delay_msec, NULL); 143 SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), delay_msec, NULL);
176 } 144 }
177 145
178 //----------------------------------------------------------------------------- 146 //-----------------------------------------------------------------------------
179 // MessagePumpWin private: 147 // MessagePumpWin protected:
180 148
181 // static 149 // static
182 LRESULT CALLBACK MessagePumpWin::WndProcThunk( 150 LRESULT CALLBACK MessagePumpWin::WndProcThunk(
183 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { 151 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
184 switch (message) { 152 switch (message) {
185 case kMsgHaveWork: 153 case kMsgHaveWork:
186 reinterpret_cast<MessagePumpWin*>(wparam)->HandleWorkMessage(); 154 reinterpret_cast<MessagePumpWin*>(wparam)->HandleWorkMessage();
187 break; 155 break;
188 case WM_TIMER: 156 case WM_TIMER:
189 reinterpret_cast<MessagePumpWin*>(wparam)->HandleTimerMessage(); 157 reinterpret_cast<MessagePumpWin*>(wparam)->HandleTimerMessage();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 if (!state_) 205 if (!state_)
238 return; 206 return;
239 207
240 state_->delegate->DoDelayedWork(&delayed_work_time_); 208 state_->delegate->DoDelayedWork(&delayed_work_time_);
241 if (!delayed_work_time_.is_null()) { 209 if (!delayed_work_time_.is_null()) {
242 // A bit gratuitous to set delayed_work_time_ again, but oh well. 210 // A bit gratuitous to set delayed_work_time_ again, but oh well.
243 ScheduleDelayedWork(delayed_work_time_); 211 ScheduleDelayedWork(delayed_work_time_);
244 } 212 }
245 } 213 }
246 214
247 void MessagePumpWin::DoRunLoop() { 215 bool MessagePumpWin::ProcessNextWindowsMessage() {
248 // IF this was just a simple PeekMessage() loop (servicing all passible work 216 MSG msg;
217 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
218 return ProcessMessageHelper(msg);
219 return false;
220 }
221
222 bool MessagePumpWin::ProcessMessageHelper(const MSG& msg) {
223 if (WM_QUIT == msg.message) {
224 // Repost the QUIT message so that it will be retrieved by the primary
225 // GetMessage() loop.
226 state_->should_quit = true;
227 PostQuitMessage(static_cast<int>(msg.wParam));
228 return false;
229 }
230
231 // While running our main message pump, we discard kMsgHaveWork messages.
232 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_)
233 return ProcessPumpReplacementMessage();
234
235 WillProcessMessage(msg);
236
237 if (state_->dispatcher) {
238 if (!state_->dispatcher->Dispatch(msg))
239 state_->should_quit = true;
240 } else {
241 TranslateMessage(&msg);
242 DispatchMessage(&msg);
243 }
244
245 DidProcessMessage(msg);
246 return true;
247 }
248
249 bool MessagePumpWin::ProcessPumpReplacementMessage() {
250 // When we encounter a kMsgHaveWork message, this method is called to peek
251 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The
252 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though
253 // a continuous stream of such messages are posted. This method carefully
254 // peeks a message while there is no chance for a kMsgHaveWork to be pending,
255 // then resets the have_work_ flag (allowing a replacement kMsgHaveWork to
256 // possibly be posted), and finally dispatches that peeked replacement. Note
257 // that the re-post of kMsgHaveWork may be asynchronous to this thread!!
258
259 MSG msg;
260 bool have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
261 DCHECK(!have_message || kMsgHaveWork != msg.message ||
262 msg.hwnd != message_hwnd_);
263
264 // Since we discarded a kMsgHaveWork message, we must update the flag.
265 InterlockedExchange(&have_work_, 0);
266
267 // TODO(darin,jar): There is risk of being lost in a sub-pump within the call
268 // to ProcessMessageHelper, which could result in no longer getting a
269 // kMsgHaveWork message until the next out-of-band call to ScheduleWork.
270
271 return have_message && ProcessMessageHelper(msg);
272 }
273
274 int MessagePumpWin::GetCurrentDelay() const {
275 if (delayed_work_time_.is_null())
276 return -1;
277
278 // Be careful here. TimeDelta has a precision of microseconds, but we want a
279 // value in milliseconds. If there are 5.5ms left, should the delay be 5 or
280 // 6? It should be 6 to avoid executing delayed work too early.
281 double timeout = ceil((delayed_work_time_ - Time::Now()).InMillisecondsF());
282
283 // If this value is negative, then we need to run delayed work soon.
284 int delay = static_cast<int>(timeout);
285 if (delay < 0)
286 delay = 0;
287
288 return delay;
289 }
290
291 //-----------------------------------------------------------------------------
292 // MessagePumpForUI private:
293
294 void MessagePumpForUI::DoRunLoop() {
295 // IF this was just a simple PeekMessage() loop (servicing all possible work
249 // queues), then Windows would try to achieve the following order according 296 // queues), then Windows would try to achieve the following order according
250 // to MSDN documentation about PeekMessage with no filter): 297 // to MSDN documentation about PeekMessage with no filter):
251 // * Sent messages 298 // * Sent messages
252 // * Posted messages 299 // * Posted messages
253 // * Sent messages (again) 300 // * Sent messages (again)
254 // * WM_PAINT messages 301 // * WM_PAINT messages
255 // * WM_TIMER messages 302 // * WM_TIMER messages
256 // 303 //
257 // Summary: none of the above classes is starved, and sent messages has twice 304 // Summary: none of the above classes is starved, and sent messages has twice
258 // the chance of being processed (i.e., reduced service time). 305 // the chance of being processed (i.e., reduced service time).
259 306
260 for (;;) { 307 for (;;) {
261 // If we do any work, we may create more messages etc., and more work may 308 // If we do any work, we may create more messages etc., and more work may
262 // possibly be waiting in another task group. When we (for example) 309 // possibly be waiting in another task group. When we (for example)
263 // ProcessNextWindowsMessage(), there is a good chance there are still more 310 // ProcessNextWindowsMessage(), there is a good chance there are still more
311 // messages waiting. On the other hand, when any of these methods return
312 // having done no work, then it is pretty unlikely that calling them again
313 // quickly will find any work to do. Finally, if they all say they had no
314 // work, then it is a good time to consider sleeping (waiting) for more
315 // work.
316
317 bool more_work_is_plausible = ProcessNextWindowsMessage();
318 if (state_->should_quit)
319 break;
320
321 more_work_is_plausible |= state_->delegate->DoWork();
322 if (state_->should_quit)
323 break;
324
325 more_work_is_plausible |=
326 state_->delegate->DoDelayedWork(&delayed_work_time_);
327 // If we did not process any delayed work, then we can assume that our
328 // existing WM_TIMER if any will fire when delayed work should run. We
329 // don't want to disturb that timer if it is already in flight. However,
330 // if we did do all remaining delayed work, then lets kill the WM_TIMER.
331 if (more_work_is_plausible && delayed_work_time_.is_null())
332 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this));
333 if (state_->should_quit)
334 break;
335
336 if (more_work_is_plausible)
337 continue;
338
339 more_work_is_plausible = state_->delegate->DoIdleWork();
340 if (state_->should_quit)
341 break;
342
343 if (more_work_is_plausible)
344 continue;
345
346 WaitForWork(); // Wait (sleep) until we have work to do again.
347 }
348 }
349
350 void MessagePumpForUI::WaitForWork() {
351 // Wait until a message is available, up to the time needed by the timer
352 // manager to fire the next set of timers.
353 int delay = GetCurrentDelay();
354 if (delay < 0) // Negative value means no timers waiting.
355 delay = INFINITE;
356
357 DWORD result;
358 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT,
359 MWMO_INPUTAVAILABLE);
360
361 if (WAIT_OBJECT_0 == result)
362 return; // A WM_* message is available.
363
364 DCHECK_NE(WAIT_FAILED, result) << GetLastError();
365 }
366
367 //-----------------------------------------------------------------------------
368 // MessagePumpForIO public:
369
370 void MessagePumpForIO::WatchObject(HANDLE object, Watcher* watcher) {
371 DCHECK(object);
372 DCHECK_NE(object, INVALID_HANDLE_VALUE);
373
374 std::vector<HANDLE>::iterator it =
375 find(objects_.begin(), objects_.end(), object);
376 if (watcher) {
377 if (it == objects_.end()) {
378 static size_t warning_multiple = 1;
379 if (objects_.size() >= warning_multiple * MAXIMUM_WAIT_OBJECTS / 2) {
380 LOG(INFO) << "More than " << warning_multiple * MAXIMUM_WAIT_OBJECTS / 2
381 << " objects being watched";
382 // This DCHECK() is an artificial limitation, meant to warn us if we
383 // start creating too many objects. It can safely be raised to a higher
384 // level, and the program is designed to handle much larger values.
385 // Before raising this limit, make sure that there is a very good reason
386 // (in your debug testing) to be watching this many objects.
387 DCHECK(2 <= warning_multiple);
388 ++warning_multiple;
389 }
390 objects_.push_back(object);
391 watchers_.push_back(watcher);
392 } else {
393 watchers_[it - objects_.begin()] = watcher;
394 }
395 } else if (it != objects_.end()) {
396 std::vector<HANDLE>::difference_type index = it - objects_.begin();
397 objects_.erase(it);
398 watchers_.erase(watchers_.begin() + index);
399 }
400 }
401
402
403 //-----------------------------------------------------------------------------
404 // MessagePumpForIO private:
405
406 void MessagePumpForIO::DoRunLoop() {
407 // IF this was just a simple PeekMessage() loop (servicing all possible work
408 // queues), then Windows would try to achieve the following order according
409 // to MSDN documentation about PeekMessage with no filter):
410 // * Sent messages
411 // * Posted messages
412 // * Sent messages (again)
413 // * WM_PAINT messages
414 // * WM_TIMER messages
415 //
416 // Summary: none of the above classes is starved, and sent messages has twice
417 // the chance of being processed (i.e., reduced service time).
418
419 for (;;) {
420 // If we do any work, we may create more messages etc., and more work may
421 // possibly be waiting in another task group. When we (for example)
422 // ProcessNextWindowsMessage(), there is a good chance there are still more
264 // messages waiting (same thing for ProcessNextObject(), which responds to 423 // messages waiting (same thing for ProcessNextObject(), which responds to
265 // only one signaled object; etc.). On the other hand, when any of these 424 // only one signaled object; etc.). On the other hand, when any of these
266 // methods return having done no work, then it is pretty unlikely that 425 // methods return having done no work, then it is pretty unlikely that
267 // calling them again quickly will find any work to do. Finally, if they 426 // calling them again quickly will find any work to do. Finally, if they
268 // all say they had no work, then it is a good time to consider sleeping 427 // all say they had no work, then it is a good time to consider sleeping
269 // (waiting) for more work. 428 // (waiting) for more work.
270 429
271 bool more_work_is_plausible = ProcessNextWindowsMessage(); 430 bool more_work_is_plausible = ProcessNextWindowsMessage();
272 if (state_->should_quit) 431 if (state_->should_quit)
273 break; 432 break;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 // If we handle more than the OS limit on the number of objects that can be 468 // If we handle more than the OS limit on the number of objects that can be
310 // waited for, we'll need to poll (sequencing through subsets of the objects 469 // waited for, we'll need to poll (sequencing through subsets of the objects
311 // that can be passed in a single OS wait call). The following is the polling 470 // that can be passed in a single OS wait call). The following is the polling
312 // interval used in that (unusual) case. (I don't have a lot of justifcation 471 // interval used in that (unusual) case. (I don't have a lot of justifcation
313 // for the specific value, but it needed to be short enough that it would not 472 // for the specific value, but it needed to be short enough that it would not
314 // add a lot of latency, and long enough that we wouldn't thrash the CPU for no 473 // add a lot of latency, and long enough that we wouldn't thrash the CPU for no
315 // reason... especially considering the silly user probably has a million tabs 474 // reason... especially considering the silly user probably has a million tabs
316 // open, etc.) 475 // open, etc.)
317 static const int kMultipleWaitPollingInterval = 20; 476 static const int kMultipleWaitPollingInterval = 20;
318 477
319 void MessagePumpWin::WaitForWork() { 478 void MessagePumpForIO::WaitForWork() {
320 // Wait until either an object is signaled or a message is available. Handle 479 // Wait until either an object is signaled or a message is available. Handle
321 // (without returning) any APCs (only the IO thread currently has APCs.) 480 // (without returning) any APCs (only the IO thread currently has APCs.)
322 481
323 // We do not support nested message loops when we have watched objects. This 482 // We do not support nested message loops when we have watched objects. This
324 // is to avoid messy recursion problems. 483 // is to avoid messy recursion problems.
325 DCHECK(objects_.empty() || state_->run_depth == 1) << 484 DCHECK(objects_.empty() || state_->run_depth == 1) <<
326 "Cannot nest a message loop when there are watched objects!"; 485 "Cannot nest a message loop when there are watched objects!";
327 486
328 int wait_flags = MWMO_ALERTABLE | MWMO_INPUTAVAILABLE; 487 int wait_flags = MWMO_ALERTABLE | MWMO_INPUTAVAILABLE;
329 488
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 return; 538 return;
380 polling_index += objs_len; 539 polling_index += objs_len;
381 } while (polling_index < total_objs); 540 } while (polling_index < total_objs);
382 // For compatibility, we didn't return sooner. This made us do *some* wait 541 // For compatibility, we didn't return sooner. This made us do *some* wait
383 // call(s) before returning. This will probably change in next rev. 542 // call(s) before returning. This will probably change in next rev.
384 if (!delay || !GetCurrentDelay()) 543 if (!delay || !GetCurrentDelay())
385 return; // No work done, but timer is ready to fire. 544 return; // No work done, but timer is ready to fire.
386 } 545 }
387 } 546 }
388 547
389 bool MessagePumpWin::ProcessNextWindowsMessage() { 548 bool MessagePumpForIO::ProcessNextObject() {
390 MSG msg;
391 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
392 return ProcessMessageHelper(msg);
393 return false;
394 }
395
396 bool MessagePumpWin::ProcessMessageHelper(const MSG& msg) {
397 if (WM_QUIT == msg.message) {
398 // Repost the QUIT message so that it will be retrieved by the primary
399 // GetMessage() loop.
400 state_->should_quit = true;
401 PostQuitMessage(static_cast<int>(msg.wParam));
402 return false;
403 }
404
405 // While running our main message pump, we discard kMsgHaveWork messages.
406 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_)
407 return ProcessPumpReplacementMessage();
408
409 WillProcessMessage(msg);
410
411 if (state_->dispatcher) {
412 if (!state_->dispatcher->Dispatch(msg))
413 state_->should_quit = true;
414 } else {
415 TranslateMessage(&msg);
416 DispatchMessage(&msg);
417 }
418
419 DidProcessMessage(msg);
420 return true;
421 }
422
423 bool MessagePumpWin::ProcessPumpReplacementMessage() {
424 // When we encounter a kMsgHaveWork message, this method is called to peek
425 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The
426 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though
427 // a continuous stream of such messages are posted. This method carefully
428 // peeks a message while there is no chance for a kMsgHaveWork to be pending,
429 // then resets the have_work_ flag (allowing a replacement kMsgHaveWork to
430 // possibly be posted), and finally dispatches that peeked replacement. Note
431 // that the re-post of kMsgHaveWork may be asynchronous to this thread!!
432
433 MSG msg;
434 bool have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
435 DCHECK(!have_message || kMsgHaveWork != msg.message ||
436 msg.hwnd != message_hwnd_);
437
438 // Since we discarded a kMsgHaveWork message, we must update the flag.
439 InterlockedExchange(&have_work_, 0);
440
441 // TODO(darin,jar): There is risk of being lost in a sub-pump within the call
442 // to ProcessMessageHelper, which could result in no longer getting a
443 // kMsgHaveWork message until the next out-of-band call to ScheduleWork.
444
445 return have_message && ProcessMessageHelper(msg);
446 }
447
448 // Note: MsgWaitMultipleObjects() can't take a nil list, and that is why I had
449 // to use SleepEx() to handle APCs when there were no objects.
450 bool MessagePumpWin::ProcessNextObject() {
451 size_t total_objs = objects_.size(); 549 size_t total_objs = objects_.size();
452 if (!total_objs) { 550 if (!total_objs) {
453 return false; 551 return false;
454 } 552 }
455 553
456 size_t polling_index = 0; // The first unprocessed object index. 554 size_t polling_index = 0; // The first unprocessed object index.
457 do { 555 do {
458 DCHECK(polling_index < total_objs); 556 DCHECK(polling_index < total_objs);
459 size_t objs_len = total_objs - polling_index; 557 size_t objs_len = total_objs - polling_index;
460 if (objs_len >= kMaxWaitObjects) 558 if (objs_len >= kMaxWaitObjects)
(...skipping 13 matching lines...) Expand all
474 return true; // We serviced a signaled object. 572 return true; // We serviced a signaled object.
475 } 573 }
476 574
477 // If an handle is invalid, it will be WAIT_FAILED. 575 // If an handle is invalid, it will be WAIT_FAILED.
478 DCHECK_EQ(WAIT_TIMEOUT, result) << GetLastError(); 576 DCHECK_EQ(WAIT_TIMEOUT, result) << GetLastError();
479 polling_index += objs_len; 577 polling_index += objs_len;
480 } while (polling_index < total_objs); 578 } while (polling_index < total_objs);
481 return false; // We serviced nothing. 579 return false; // We serviced nothing.
482 } 580 }
483 581
484 bool MessagePumpWin::SignalWatcher(size_t object_index) { 582 bool MessagePumpForIO::SignalWatcher(size_t object_index) {
485 // Signal the watcher corresponding to the given index. 583 // Signal the watcher corresponding to the given index.
486 584
487 DCHECK(objects_.size() > object_index); 585 DCHECK(objects_.size() > object_index);
488 586
489 // On reception of OnObjectSignaled() to a Watcher object, it may call 587 // On reception of OnObjectSignaled() to a Watcher object, it may call
490 // WatchObject(). watchers_ and objects_ will be modified. This is expected, 588 // WatchObject(). watchers_ and objects_ will be modified. This is expected,
491 // so don't be afraid if, while tracing a OnObjectSignaled() function, the 589 // so don't be afraid if, while tracing a OnObjectSignaled() function, the
492 // corresponding watchers_[result] is non-existant. 590 // corresponding watchers_[result] is non-existant.
493 watchers_[object_index]->OnObjectSignaled(objects_[object_index]); 591 watchers_[object_index]->OnObjectSignaled(objects_[object_index]);
494 592
495 // Signaled objects tend to be removed from the watch list, and then added 593 // Signaled objects tend to be removed from the watch list, and then added
496 // back (appended). As a result, they move to the end of the objects_ array, 594 // back (appended). As a result, they move to the end of the objects_ array,
497 // and this should make their service "fair" (no HANDLEs should be starved). 595 // and this should make their service "fair" (no HANDLEs should be starved).
498 596
499 return true; 597 return true;
500 } 598 }
501 599
502 int MessagePumpWin::GetCurrentDelay() const {
503 if (delayed_work_time_.is_null())
504 return -1;
505
506 // Be careful here. TimeDelta has a precision of microseconds, but we want a
507 // value in milliseconds. If there are 5.5ms left, should the delay be 5 or
508 // 6? It should be 6 to avoid executing delayed work too early.
509 double timeout = ceil((delayed_work_time_ - Time::Now()).InMillisecondsF());
510
511 // If this value is negative, then we need to run delayed work soon.
512 int delay = static_cast<int>(timeout);
513 if (delay < 0)
514 delay = 0;
515
516 return delay;
517 }
518
519 } // namespace base 600 } // namespace base
520
OLDNEW
« no previous file with comments | « base/message_pump_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698