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

Side by Side Diff: base/synchronization/waitable_event_win.cc

Issue 2433773005: Move OS_WIN specific logic in MessagePumpDefault::Run into waitable_event_win.cc (Closed)
Patch Set: Fixed posix implementation of WaitableEvent::Wait() Created 4 years, 1 month 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 (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/synchronization/waitable_event.h" 5 #include "base/synchronization/waitable_event.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <algorithm>
10 #include <utility> 11 #include <utility>
11 12
12 #include "base/debug/activity_tracker.h" 13 #include "base/debug/activity_tracker.h"
13 #include "base/logging.h" 14 #include "base/logging.h"
14 #include "base/numerics/safe_conversions.h" 15 #include "base/numerics/safe_conversions.h"
15 #include "base/threading/thread_restrictions.h" 16 #include "base/threading/thread_restrictions.h"
16 #include "base/time/time.h" 17 #include "base/time/time.h"
17 18
18 namespace base { 19 namespace base {
19 20
(...skipping 17 matching lines...) Expand all
37 38
38 void WaitableEvent::Reset() { 39 void WaitableEvent::Reset() {
39 ResetEvent(handle_.Get()); 40 ResetEvent(handle_.Get());
40 } 41 }
41 42
42 void WaitableEvent::Signal() { 43 void WaitableEvent::Signal() {
43 SetEvent(handle_.Get()); 44 SetEvent(handle_.Get());
44 } 45 }
45 46
46 bool WaitableEvent::IsSignaled() { 47 bool WaitableEvent::IsSignaled() {
47 return TimedWait(TimeDelta()); 48 DWORD result = WaitForSingleObject(handle_.Get(), 0);
49 DCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT)
50 << "Unexpected WaitForSingleObject result " << result;
51 return result == WAIT_OBJECT_0;
48 } 52 }
49 53
50 void WaitableEvent::Wait() { 54 void WaitableEvent::Wait() {
51 // Record the event that this thread is blocking upon (for hang diagnosis). 55 // Record the event that this thread is blocking upon (for hang diagnosis).
52 base::debug::ScopedEventWaitActivity event_activity(this); 56 base::debug::ScopedEventWaitActivity event_activity(this);
53 57
54 base::ThreadRestrictions::AssertWaitAllowed(); 58 base::ThreadRestrictions::AssertWaitAllowed();
55 DWORD result = WaitForSingleObject(handle_.Get(), INFINITE); 59 DWORD result = WaitForSingleObject(handle_.Get(), INFINITE);
56 // It is most unexpected that this should ever fail. Help consumers learn 60 // It is most unexpected that this should ever fail. Help consumers learn
57 // about it if it should ever fail. 61 // about it if it should ever fail.
58 DCHECK_EQ(WAIT_OBJECT_0, result) << "WaitForSingleObject failed"; 62 DCHECK_EQ(WAIT_OBJECT_0, result) << "WaitForSingleObject failed";
59 } 63 }
60 64
61 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { 65 namespace {
66 // Helper function called from TimedWait and TimedWaitUntil.
67 bool WaitUntil(HANDLE handle, const TimeTicks& now, const TimeTicks& end_time) {
68 TimeDelta delta = end_time - now;
69 DCHECK_GT(delta, TimeDelta());
70
71 do {
72 // On Windows, waiting for less than 1 ms results in WaitForSingleObject
73 // returning promptly which may result in the caller code spinning.
74 // We need to ensure that we specify at least the minimally possible 1 ms
75 // delay unless the initial timeout was exactly zero.
76 delta = std::max(delta, TimeDelta::FromMilliseconds(1));
77 // Truncate the timeout to milliseconds.
78 DWORD timeout_ms = saturated_cast<DWORD>(delta.InMilliseconds());
79 DWORD result = WaitForSingleObject(handle, timeout_ms);
80 DCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT)
81 << "Unexpected WaitForSingleObject result " << result;
82 switch (result) {
83 case WAIT_OBJECT_0:
84 return true;
85 case WAIT_TIMEOUT:
86 // TimedWait can time out earlier than the specified |timeout| on
87 // Windows. To make this consistent with the posix implementation we
88 // should guarantee that TimedWait doesn't return earlier than the
89 // specified |max_time| and wait again for the remaining time.
90 delta = end_time - TimeTicks::Now();
91 break;
92 }
93 } while (delta > TimeDelta());
94 return false;
95 }
96 } // namespace
97
98 bool WaitableEvent::TimedWait(const TimeDelta& max_delta) {
62 // Record the event that this thread is blocking upon (for hang diagnosis). 99 // Record the event that this thread is blocking upon (for hang diagnosis).
63 base::debug::ScopedEventWaitActivity event_activity(this); 100 base::debug::ScopedEventWaitActivity event_activity(this);
101 base::ThreadRestrictions::AssertWaitAllowed();
danakj 2016/11/16 22:57:29 This should be after the check for is_zero right?
stanisc 2016/11/17 19:42:22 That's what I had before, but I thought you sugges
64 102
65 DCHECK_GE(max_time, TimeDelta()); 103 DCHECK_GE(max_delta, TimeDelta());
66 if (!max_time.is_zero()) 104 if (max_delta.is_zero())
67 base::ThreadRestrictions::AssertWaitAllowed(); 105 return IsSignaled();
68 106
69 // Truncate the timeout to milliseconds. The API specifies that this method 107 TimeTicks now(TimeTicks::Now());
70 // can return in less than |max_time| (when returning false), as the argument 108 // TimeTicks takes care of overflow including the cases when max_delta
71 // is the maximum time that a caller is willing to wait. 109 // is a maximum value.
72 DWORD timeout = saturated_cast<DWORD>(max_time.InMilliseconds()); 110 return WaitUntil(handle_.Get(), now, now + max_delta);
111 }
73 112
74 DWORD result = WaitForSingleObject(handle_.Get(), timeout); 113 bool WaitableEvent::TimedWaitUntil(const TimeTicks& end_time) {
75 switch (result) { 114 // Record the event that this thread is blocking upon (for hang diagnosis).
76 case WAIT_OBJECT_0: 115 base::debug::ScopedEventWaitActivity event_activity(this);
77 return true; 116 base::ThreadRestrictions::AssertWaitAllowed();
danakj 2016/11/16 22:57:29 same, but we should check for is_zero explicitly h
stanisc 2016/11/17 19:42:22 Moved the assert below the check. Shouldn't zero T
danakj 2016/11/17 21:11:08 0 would be handled, but other things too. I don't
stanisc 2016/11/18 02:13:47 OK, I've added a special case for zero TimeTicks.
78 case WAIT_TIMEOUT: 117
79 return false; 118 TimeTicks now(TimeTicks::Now());
80 } 119 if (end_time <= now)
81 // It is most unexpected that this should ever fail. Help consumers learn 120 return IsSignaled();
82 // about it if it should ever fail. 121
83 NOTREACHED() << "WaitForSingleObject failed"; 122 return WaitUntil(handle_.Get(), now, end_time);
84 return false;
85 } 123 }
86 124
87 // static 125 // static
88 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { 126 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) {
89 DCHECK(count) << "Cannot wait on no events"; 127 DCHECK(count) << "Cannot wait on no events";
90 128
91 // Record an event (the first) that this thread is blocking upon. 129 // Record an event (the first) that this thread is blocking upon.
92 base::debug::ScopedEventWaitActivity event_activity(events[0]); 130 base::debug::ScopedEventWaitActivity event_activity(events[0]);
93 131
94 base::ThreadRestrictions::AssertWaitAllowed(); 132 base::ThreadRestrictions::AssertWaitAllowed();
(...skipping 12 matching lines...) Expand all
107 INFINITE); // no timeout 145 INFINITE); // no timeout
108 if (result >= WAIT_OBJECT_0 + count) { 146 if (result >= WAIT_OBJECT_0 + count) {
109 DPLOG(FATAL) << "WaitForMultipleObjects failed"; 147 DPLOG(FATAL) << "WaitForMultipleObjects failed";
110 return 0; 148 return 0;
111 } 149 }
112 150
113 return result - WAIT_OBJECT_0; 151 return result - WAIT_OBJECT_0;
114 } 152 }
115 153
116 } // namespace base 154 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698