|
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 |
|
3 // found in the LICENSE file. |
|
4 |
|
5 #include "base/waitable_event.h" |
|
6 |
|
7 #include <math.h> |
|
8 #include <windows.h> |
|
9 |
|
10 #include "base/logging.h" |
|
11 #include "base/time.h" |
|
12 |
|
13 namespace base { |
|
14 |
|
15 WaitableEvent::WaitableEvent(bool manual_reset, bool signaled) |
|
16 : handle_(CreateEvent(NULL, manual_reset, signaled, NULL)) { |
|
17 // We're probably going to crash anyways if this is ever NULL, so we might as |
|
18 // well make our stack reports more informative by crashing here. |
|
19 CHECK(handle_); |
|
20 } |
|
21 |
|
22 WaitableEvent::WaitableEvent(HANDLE handle) |
|
23 : handle_(handle) { |
|
24 CHECK(handle) << "Tried to create WaitableEvent from NULL handle"; |
|
25 } |
|
26 |
|
27 WaitableEvent::~WaitableEvent() { |
|
28 CloseHandle(handle_); |
|
29 } |
|
30 |
|
31 HANDLE WaitableEvent::Release() { |
|
32 HANDLE rv = handle_; |
|
33 handle_ = INVALID_HANDLE_VALUE; |
|
34 return rv; |
|
35 } |
|
36 |
|
37 void WaitableEvent::Reset() { |
|
38 ResetEvent(handle_); |
|
39 } |
|
40 |
|
41 void WaitableEvent::Signal() { |
|
42 SetEvent(handle_); |
|
43 } |
|
44 |
|
45 bool WaitableEvent::IsSignaled() { |
|
46 return TimedWait(TimeDelta::FromMilliseconds(0)); |
|
47 } |
|
48 |
|
49 bool WaitableEvent::Wait() { |
|
50 DWORD result = WaitForSingleObject(handle_, INFINITE); |
|
51 // It is most unexpected that this should ever fail. Help consumers learn |
|
52 // about it if it should ever fail. |
|
53 DCHECK(result == WAIT_OBJECT_0) << "WaitForSingleObject failed"; |
|
54 return result == WAIT_OBJECT_0; |
|
55 } |
|
56 |
|
57 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { |
|
58 DCHECK(max_time >= TimeDelta::FromMicroseconds(0)); |
|
59 // Be careful here. TimeDelta has a precision of microseconds, but this API |
|
60 // is in milliseconds. If there are 5.5ms left, should the delay be 5 or 6? |
|
61 // It should be 6 to avoid returning too early. |
|
62 double timeout = ceil(max_time.InMillisecondsF()); |
|
63 DWORD result = WaitForSingleObject(handle_, static_cast<DWORD>(timeout)); |
|
64 switch (result) { |
|
65 case WAIT_OBJECT_0: |
|
66 return true; |
|
67 case WAIT_TIMEOUT: |
|
68 return false; |
|
69 } |
|
70 // It is most unexpected that this should ever fail. Help consumers learn |
|
71 // about it if it should ever fail. |
|
72 NOTREACHED() << "WaitForSingleObject failed"; |
|
73 return false; |
|
74 } |
|
75 |
|
76 // static |
|
77 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { |
|
78 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; |
|
79 CHECK(count <= MAXIMUM_WAIT_OBJECTS) |
|
80 << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany"; |
|
81 |
|
82 for (size_t i = 0; i < count; ++i) |
|
83 handles[i] = events[i]->handle(); |
|
84 |
|
85 DWORD result = |
|
86 WaitForMultipleObjects(count, handles, |
|
87 FALSE, // don't wait for all the objects |
|
88 INFINITE); // no timeout |
|
89 if (result < WAIT_OBJECT_0 || result >= WAIT_OBJECT_0 + count) { |
|
90 NOTREACHED() << "WaitForMultipleObjects failed: " << GetLastError(); |
|
91 return 0; |
|
92 } |
|
93 |
|
94 return result - WAIT_OBJECT_0; |
|
95 } |
|
96 |
|
97 } // namespace base |