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

Side by Side Diff: base/reactor.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months 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/reactor.h ('k') | base/reactor_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16
17 #include "omaha/base/reactor.h"
18
19 #include <vector>
20 #include "base/scoped_ptr.h"
21 #include "omaha/base/debug.h"
22 #include "omaha/base/error.h"
23 #include "omaha/base/logging.h"
24 #include "omaha/base/event_handler.h"
25
26 namespace omaha {
27
28 Reactor::Reactor() {
29 CORE_LOG(L4, (_T("[Reactor::Reactor]")));
30 ::InitializeCriticalSection(&cs_);
31 }
32
33 Reactor::~Reactor() {
34 CORE_LOG(L4, (_T("[Reactor::~Reactor]")));
35
36 // Each handle must be unregistered before destroying the reactor.
37 ASSERT1(handlers_.empty());
38 ::DeleteCriticalSection(&cs_);
39 }
40
41 // The reactor loop is just an efficient wait, as the demultiplexing of the
42 // events is actually done by the OS thread pool.
43 // TODO(omaha): replace the alertable wait with waiting on an event and provide
44 // a method for the reactor to stop handling events.
45 HRESULT Reactor::HandleEvents() {
46 CORE_LOG(L1, (_T("[Reactor::HandleEvents]")));
47 VERIFY1(::SleepEx(INFINITE, true) == WAIT_IO_COMPLETION);
48 CORE_LOG(L1, (_T("[Reactor::HandleEvents exit]")));
49 return S_OK;
50 }
51
52 void __stdcall Reactor::Callback(void* param, BOOLEAN timer_or_wait) {
53 ASSERT1(param);
54
55 // Since we wait an INFINITE the wait handle is always signaled.
56 VERIFY1(!timer_or_wait);
57 RegistrationState* state = static_cast<RegistrationState*>(param);
58 ASSERT1(state->reactor);
59 state->reactor->DoCallback(state);
60 }
61
62 // Method does not check to see if the same handle is registered twice.
63 HRESULT Reactor::RegisterHandle(HANDLE handle,
64 EventHandler* event_handler,
65 uint32 flags) {
66 ASSERT1(handle);
67 ASSERT1(event_handler);
68
69 if (!handle || !event_handler) {
70 return E_INVALIDARG;
71 }
72
73 scoped_ptr<RegistrationState> state(new RegistrationState);
74 state->event_handler = event_handler;
75 state->handle = handle;
76 state->reactor = this;
77 state->flags = flags | WT_EXECUTEONLYONCE;
78
79 // The reactor only calls the handler once.
80 ASSERT1(WT_EXECUTEDEFAULT == 0);
81
82 // As soon as the handle is registered, the thread pool can queue up a
83 // callback and reenter the reactor on a different thread.
84 // Acquire the critical section before registering the handle.
85 ::EnterCriticalSection(&cs_);
86 #if DEBUG
87 // The same handle should not be registered multiple times.
88 std::vector<RegistrationState*>::iterator it = handlers_.begin();
89 for (; it != handlers_.end(); ++it) {
90 ASSERT((*it)->handle != handle, (_T("[already registered %d]"), handle));
91 }
92 #endif
93 bool res = !!::RegisterWaitForSingleObject(&state->wait_handle,
94 state->handle,
95 &Reactor::Callback,
96 state.get(),
97 INFINITE,
98 state->flags);
99 HRESULT hr = res ? S_OK : HRESULTFromLastError();
100 if (SUCCEEDED(hr)) {
101 handlers_.push_back(state.release());
102 }
103 ::LeaveCriticalSection(&cs_);
104
105 return hr;
106 }
107
108 HRESULT Reactor::RegisterHandle(HANDLE handle) {
109 ::EnterCriticalSection(&cs_);
110 HRESULT hr = DoRegisterHandle(handle);
111 ::LeaveCriticalSection(&cs_);
112 return hr;
113 }
114
115 HRESULT Reactor::DoRegisterHandle(HANDLE handle) {
116 ASSERT1(handle);
117 std::vector<RegistrationState*>::iterator it = handlers_.begin();
118 for (; it != handlers_.end(); ++it) {
119 if ((*it)->handle == handle) {
120 break;
121 }
122 }
123 if (it == handlers_.end()) {
124 // The handle is not registered with the reactor anymore. Registering the
125 // the handle again is not possible.
126 return E_FAIL;
127 }
128
129 // Unregister and register the handle again. Unregistering is an non blocking
130 // call.
131 RegistrationState* state = *it;
132 bool res = !!::UnregisterWaitEx(state->wait_handle, NULL);
133 if (!res && ::GetLastError() != ERROR_IO_PENDING) {
134 return HRESULTFromLastError();
135 }
136 if (!::RegisterWaitForSingleObject(&state->wait_handle,
137 state->handle,
138 &Reactor::Callback,
139 state,
140 INFINITE,
141 state->flags)) {
142 return HRESULTFromLastError();
143 }
144 return S_OK;
145 }
146
147 HRESULT Reactor::UnregisterHandle(HANDLE handle) {
148 ASSERT1(handle);
149 if (!handle) {
150 return E_INVALIDARG;
151 }
152
153 // Attempts to take the ownership of the registration state for the handle.
154 // If taking the ownership does not succeed, it means the handle has already
155 // been unregistered.
156 scoped_ptr<RegistrationState> state(ReleaseHandlerState(handle));
157 if (!state.get()) {
158 return E_UNEXPECTED;
159 }
160
161 // Unregisters the wait handle from the thread pool. The call blocks waiting
162 // for any pending callbacks to finish. No lock is being held while waiting
163 // here. If there is no callback pending, the call will succeed right away.
164 // Otherwise, if a callback has already started, the call waits for the
165 // callback to complete.
166 bool res = !!::UnregisterWaitEx(state->wait_handle, INVALID_HANDLE_VALUE);
167
168 // Clear the registration state, as a defensive programming measure and
169 // for debugging purposes.
170 state->reactor = NULL;
171 state->handle = NULL;
172 state->wait_handle = NULL;
173 state->event_handler = NULL;
174
175 return res ? S_OK : HRESULTFromLastError();
176 }
177
178 void Reactor::DoCallback(RegistrationState* state) {
179 ASSERT1(state);
180 ASSERT1(state->event_handler);
181 ASSERT1(state->handle);
182 state->event_handler->HandleEvent(state->handle);
183 }
184
185 // Looks up the registration state for a handle and releases the ownership
186 // of it to the caller. As the clean up of the state can happen from multiple
187 // places, the transfer of ownership ensures the clean up happens once and
188 // only once.
189 Reactor::RegistrationState* Reactor::ReleaseHandlerState(HANDLE handle) {
190 RegistrationState* registration_state = NULL;
191 ::EnterCriticalSection(&cs_);
192 std::vector<RegistrationState*>::iterator it = handlers_.begin();
193 for (; it != handlers_.end(); ++it) {
194 if ((*it)->handle == handle) {
195 registration_state = *it;
196 handlers_.erase(it);
197 break;
198 }
199 }
200 ::LeaveCriticalSection(&cs_);
201 return registration_state;
202 }
203
204 } // namespace omaha
205
OLDNEW
« no previous file with comments | « base/reactor.h ('k') | base/reactor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698