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

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: Special handling of is_null() TimeTicks in TimedWaitUntil 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() {
55 base::ThreadRestrictions::AssertWaitAllowed();
51 // Record the event that this thread is blocking upon (for hang diagnosis). 56 // Record the event that this thread is blocking upon (for hang diagnosis).
52 base::debug::ScopedEventWaitActivity event_activity(this); 57 base::debug::ScopedEventWaitActivity event_activity(this);
53 58
54 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
danakj 2016/11/29 02:46:45 nit: whitespace lines around the namespace { and }
stanisc 2016/11/29 22:33:21 Done.
97
98 bool WaitableEvent::TimedWait(const TimeDelta& max_delta) {
danakj 2016/11/29 02:46:45 same name nit
stanisc 2016/11/29 22:33:21 Done.
99 DCHECK_GE(max_delta, TimeDelta());
100 if (max_delta.is_zero())
101 return IsSignaled();
102
103 base::ThreadRestrictions::AssertWaitAllowed();
62 // Record the event that this thread is blocking upon (for hang diagnosis). 104 // Record the event that this thread is blocking upon (for hang diagnosis).
63 base::debug::ScopedEventWaitActivity event_activity(this); 105 base::debug::ScopedEventWaitActivity event_activity(this);
64 106
65 DCHECK_GE(max_time, TimeDelta()); 107 TimeTicks now(TimeTicks::Now());
66 if (!max_time.is_zero()) 108 // TimeTicks takes care of overflow including the cases when max_delta
67 base::ThreadRestrictions::AssertWaitAllowed(); 109 // is a maximum value.
110 return WaitUntil(handle_.Get(), now, now + max_delta);
111 }
68 112
69 // Truncate the timeout to milliseconds. The API specifies that this method 113 bool WaitableEvent::TimedWaitUntil(const TimeTicks& end_time) {
70 // can return in less than |max_time| (when returning false), as the argument 114 if (end_time.is_null())
71 // is the maximum time that a caller is willing to wait. 115 return IsSignaled();
72 DWORD timeout = saturated_cast<DWORD>(max_time.InMilliseconds());
73 116
74 DWORD result = WaitForSingleObject(handle_.Get(), timeout); 117 base::ThreadRestrictions::AssertWaitAllowed();
75 switch (result) { 118 // Record the event that this thread is blocking upon (for hang diagnosis).
76 case WAIT_OBJECT_0: 119 base::debug::ScopedEventWaitActivity event_activity(this);
77 return true; 120
78 case WAIT_TIMEOUT: 121 TimeTicks now(TimeTicks::Now());
79 return false; 122 if (end_time <= now)
80 } 123 return IsSignaled();
81 // It is most unexpected that this should ever fail. Help consumers learn 124
82 // about it if it should ever fail. 125 return WaitUntil(handle_.Get(), now, end_time);
83 NOTREACHED() << "WaitForSingleObject failed";
84 return false;
85 } 126 }
86 127
87 // static 128 // static
88 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { 129 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) {
89 DCHECK(count) << "Cannot wait on no events"; 130 DCHECK(count) << "Cannot wait on no events";
90 131
132 base::ThreadRestrictions::AssertWaitAllowed();
91 // Record an event (the first) that this thread is blocking upon. 133 // Record an event (the first) that this thread is blocking upon.
92 base::debug::ScopedEventWaitActivity event_activity(events[0]); 134 base::debug::ScopedEventWaitActivity event_activity(events[0]);
93 135
94 base::ThreadRestrictions::AssertWaitAllowed();
95 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 136 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
96 CHECK_LE(count, static_cast<size_t>(MAXIMUM_WAIT_OBJECTS)) 137 CHECK_LE(count, static_cast<size_t>(MAXIMUM_WAIT_OBJECTS))
97 << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany"; 138 << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany";
98 139
99 for (size_t i = 0; i < count; ++i) 140 for (size_t i = 0; i < count; ++i)
100 handles[i] = events[i]->handle(); 141 handles[i] = events[i]->handle();
101 142
102 // The cast is safe because count is small - see the CHECK above. 143 // The cast is safe because count is small - see the CHECK above.
103 DWORD result = 144 DWORD result =
104 WaitForMultipleObjects(static_cast<DWORD>(count), 145 WaitForMultipleObjects(static_cast<DWORD>(count),
105 handles, 146 handles,
106 FALSE, // don't wait for all the objects 147 FALSE, // don't wait for all the objects
107 INFINITE); // no timeout 148 INFINITE); // no timeout
108 if (result >= WAIT_OBJECT_0 + count) { 149 if (result >= WAIT_OBJECT_0 + count) {
109 DPLOG(FATAL) << "WaitForMultipleObjects failed"; 150 DPLOG(FATAL) << "WaitForMultipleObjects failed";
110 return 0; 151 return 0;
111 } 152 }
112 153
113 return result - WAIT_OBJECT_0; 154 return result - WAIT_OBJECT_0;
114 } 155 }
115 156
116 } // namespace base 157 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698