OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 | |
OLD | NEW |