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

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: Addressed CR feedback Created 4 years 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
« no previous file with comments | « base/synchronization/waitable_event_unittest.cc ('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) 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
67 // Helper function called from TimedWait and TimedWaitUntil.
68 bool WaitUntil(HANDLE handle, const TimeTicks& now, const TimeTicks& end_time) {
69 TimeDelta delta = end_time - now;
70 DCHECK_GT(delta, TimeDelta());
71
72 do {
73 // On Windows, waiting for less than 1 ms results in WaitForSingleObject
74 // returning promptly which may result in the caller code spinning.
75 // We need to ensure that we specify at least the minimally possible 1 ms
76 // delay unless the initial timeout was exactly zero.
77 delta = std::max(delta, TimeDelta::FromMilliseconds(1));
78 // Truncate the timeout to milliseconds.
79 DWORD timeout_ms = saturated_cast<DWORD>(delta.InMilliseconds());
80 DWORD result = WaitForSingleObject(handle, timeout_ms);
81 DCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT)
82 << "Unexpected WaitForSingleObject result " << result;
83 switch (result) {
84 case WAIT_OBJECT_0:
85 return true;
86 case WAIT_TIMEOUT:
87 // TimedWait can time out earlier than the specified |timeout| on
88 // Windows. To make this consistent with the posix implementation we
89 // should guarantee that TimedWait doesn't return earlier than the
90 // specified |max_time| and wait again for the remaining time.
91 delta = end_time - TimeTicks::Now();
92 break;
93 }
94 } while (delta > TimeDelta());
95 return false;
96 }
97
98 } // namespace
99
100 bool WaitableEvent::TimedWait(const TimeDelta& wait_delta) {
101 DCHECK_GE(wait_delta, TimeDelta());
102 if (wait_delta.is_zero())
103 return IsSignaled();
104
105 base::ThreadRestrictions::AssertWaitAllowed();
62 // Record the event that this thread is blocking upon (for hang diagnosis). 106 // Record the event that this thread is blocking upon (for hang diagnosis).
63 base::debug::ScopedEventWaitActivity event_activity(this); 107 base::debug::ScopedEventWaitActivity event_activity(this);
64 108
65 DCHECK_GE(max_time, TimeDelta()); 109 TimeTicks now(TimeTicks::Now());
66 if (!max_time.is_zero()) 110 // TimeTicks takes care of overflow including the cases when wait_delta
67 base::ThreadRestrictions::AssertWaitAllowed(); 111 // is a maximum value.
112 return WaitUntil(handle_.Get(), now, now + wait_delta);
113 }
68 114
69 // Truncate the timeout to milliseconds. The API specifies that this method 115 bool WaitableEvent::TimedWaitUntil(const TimeTicks& end_time) {
70 // can return in less than |max_time| (when returning false), as the argument 116 if (end_time.is_null())
71 // is the maximum time that a caller is willing to wait. 117 return IsSignaled();
72 DWORD timeout = saturated_cast<DWORD>(max_time.InMilliseconds());
73 118
74 DWORD result = WaitForSingleObject(handle_.Get(), timeout); 119 base::ThreadRestrictions::AssertWaitAllowed();
75 switch (result) { 120 // Record the event that this thread is blocking upon (for hang diagnosis).
76 case WAIT_OBJECT_0: 121 base::debug::ScopedEventWaitActivity event_activity(this);
77 return true; 122
78 case WAIT_TIMEOUT: 123 TimeTicks now(TimeTicks::Now());
79 return false; 124 if (end_time <= now)
80 } 125 return IsSignaled();
81 // It is most unexpected that this should ever fail. Help consumers learn 126
82 // about it if it should ever fail. 127 return WaitUntil(handle_.Get(), now, end_time);
83 NOTREACHED() << "WaitForSingleObject failed";
84 return false;
85 } 128 }
86 129
87 // static 130 // static
88 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { 131 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) {
89 DCHECK(count) << "Cannot wait on no events"; 132 DCHECK(count) << "Cannot wait on no events";
90 133
134 base::ThreadRestrictions::AssertWaitAllowed();
91 // Record an event (the first) that this thread is blocking upon. 135 // Record an event (the first) that this thread is blocking upon.
92 base::debug::ScopedEventWaitActivity event_activity(events[0]); 136 base::debug::ScopedEventWaitActivity event_activity(events[0]);
93 137
94 base::ThreadRestrictions::AssertWaitAllowed();
95 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 138 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
96 CHECK_LE(count, static_cast<size_t>(MAXIMUM_WAIT_OBJECTS)) 139 CHECK_LE(count, static_cast<size_t>(MAXIMUM_WAIT_OBJECTS))
97 << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany"; 140 << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany";
98 141
99 for (size_t i = 0; i < count; ++i) 142 for (size_t i = 0; i < count; ++i)
100 handles[i] = events[i]->handle(); 143 handles[i] = events[i]->handle();
101 144
102 // The cast is safe because count is small - see the CHECK above. 145 // The cast is safe because count is small - see the CHECK above.
103 DWORD result = 146 DWORD result =
104 WaitForMultipleObjects(static_cast<DWORD>(count), 147 WaitForMultipleObjects(static_cast<DWORD>(count),
105 handles, 148 handles,
106 FALSE, // don't wait for all the objects 149 FALSE, // don't wait for all the objects
107 INFINITE); // no timeout 150 INFINITE); // no timeout
108 if (result >= WAIT_OBJECT_0 + count) { 151 if (result >= WAIT_OBJECT_0 + count) {
109 DPLOG(FATAL) << "WaitForMultipleObjects failed"; 152 DPLOG(FATAL) << "WaitForMultipleObjects failed";
110 return 0; 153 return 0;
111 } 154 }
112 155
113 return result - WAIT_OBJECT_0; 156 return result - WAIT_OBJECT_0;
114 } 157 }
115 158
116 } // namespace base 159 } // namespace base
OLDNEW
« no previous file with comments | « base/synchronization/waitable_event_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698