OLD | NEW |
| (Empty) |
1 // Copyright 2004-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 #include "omaha/base/thread.h" | |
17 | |
18 #include "omaha/base/debug.h" | |
19 #include "omaha/base/exception_barrier.h" | |
20 #include "omaha/base/logging.h" | |
21 #include "omaha/base/time.h" | |
22 | |
23 namespace omaha { | |
24 | |
25 // The system keeps an event associated with the thread message queue for a | |
26 // while even after the thread is dead. It can appear as a handle leak in the | |
27 // unit test but in fact it is not. | |
28 | |
29 Thread::Thread() : thread_id_(0), thread_(NULL) { | |
30 } | |
31 | |
32 Thread::~Thread() { | |
33 if (thread_) { | |
34 VERIFY1(CloseHandle(thread_)); | |
35 } | |
36 thread_ = NULL; | |
37 } | |
38 | |
39 // This is the thread proc function as required by win32. | |
40 DWORD __stdcall Thread::Prepare(void* this_pointer) { | |
41 ExceptionBarrier eb; | |
42 | |
43 ASSERT1(this_pointer); | |
44 Thread * this_thread = reinterpret_cast<Thread*>(this_pointer); | |
45 Runnable * this_runner = this_thread->runner_; | |
46 | |
47 // Create a message queue. Our thread should have one. | |
48 MSG message = {0}; | |
49 PeekMessage(&message, NULL, WM_USER, WM_USER, PM_NOREMOVE); | |
50 | |
51 // Start method is waiting on this gate to be open in order | |
52 // to proceed. By opening gate we say: OK thread is running. | |
53 this_thread->start_gate_.Open(); | |
54 | |
55 // Now call the interface method. We are done. | |
56 UTIL_LOG(L4, (L"Thread::Prepare calling thread's Run()")); | |
57 this_runner->Run(); | |
58 | |
59 return 0; | |
60 } | |
61 | |
62 // Starts the thread. It does not return until the thread is started. | |
63 bool Thread::Start(Runnable* runner) { | |
64 ASSERT1(runner); | |
65 | |
66 // Allow the thread object to be reused by cleaning its state up. | |
67 if (thread_) { | |
68 VERIFY1(CloseHandle(thread_)); | |
69 } | |
70 start_gate_.Close(); | |
71 | |
72 runner_ = runner; | |
73 thread_ = CreateThread(NULL, // default security attributes | |
74 0, // use default stack size | |
75 &Thread::Prepare, // thread function | |
76 this, // argument to thread function | |
77 0, // use default creation flags | |
78 &thread_id_); // returns the thread identifier | |
79 if (!thread_) { | |
80 return false; | |
81 } | |
82 // Wait until the newly created thread opens the gate for us. | |
83 return start_gate_.Wait(INFINITE); | |
84 } | |
85 | |
86 DWORD Thread::GetThreadId() const { | |
87 return thread_id_; | |
88 } | |
89 | |
90 HANDLE Thread::GetThreadHandle() const { | |
91 return thread_; | |
92 } | |
93 | |
94 bool Thread::Suspend() { | |
95 return (static_cast<DWORD>(-1) != SuspendThread(thread_)); | |
96 } | |
97 | |
98 bool Thread::Resume() { | |
99 return (static_cast<DWORD>(-1) != ResumeThread(thread_)); | |
100 } | |
101 | |
102 bool Thread::Terminate(int exit_code) { | |
103 return TRUE == TerminateThread(thread_, exit_code); | |
104 } | |
105 | |
106 bool Thread::SetPriority(int priority) { | |
107 return TRUE == SetThreadPriority(thread_, priority); | |
108 } | |
109 | |
110 bool Thread::GetPriority(int* priority) const { | |
111 if (!priority) { | |
112 return false; | |
113 } | |
114 *priority = GetThreadPriority(thread_); | |
115 return THREAD_PRIORITY_ERROR_RETURN != *priority; | |
116 } | |
117 | |
118 // Waits for handle to become signaled. | |
119 bool Thread::WaitTillExit(DWORD msec) const { | |
120 if (!Running()) { | |
121 return true; | |
122 } | |
123 return WAIT_OBJECT_0 == WaitForSingleObject(thread_, msec); | |
124 } | |
125 | |
126 // Checks if the thread is running. | |
127 bool Thread::Running() const { | |
128 if (NULL == thread_) { | |
129 return false; | |
130 } | |
131 return WAIT_TIMEOUT == WaitForSingleObject(thread_, 0); | |
132 } | |
133 | |
134 // Executes an APC request. | |
135 void __stdcall Thread::APCProc(ULONG_PTR param) { | |
136 ApcInfo* pInfo = reinterpret_cast<ApcInfo*>(param); | |
137 if (pInfo) { | |
138 if (pInfo->receiver_) { | |
139 pInfo->receiver_->OnApc(pInfo->param_); | |
140 } | |
141 // Deallocates what was allocated in QueueApc. | |
142 delete pInfo; | |
143 } | |
144 } | |
145 | |
146 // ApcReceiver wants to execute its OnApc function in the | |
147 // context of this thread. | |
148 bool Thread::QueueApc(ApcReceiver* receiver, ULONG_PTR param) { | |
149 ASSERT1(receiver); | |
150 if (!Running()) { | |
151 // No reason to queue anything to not running thread. | |
152 return true; | |
153 } | |
154 | |
155 // This allocation will be freed in Thread::APCProc | |
156 ApcInfo* pInfo = new ApcInfo(); | |
157 pInfo->receiver_ = receiver; | |
158 pInfo->param_ = param; | |
159 return 0 != QueueUserAPC(&Thread::APCProc, | |
160 thread_, | |
161 reinterpret_cast<ULONG_PTR>(pInfo)); | |
162 } | |
163 | |
164 bool Thread::PostMessage(UINT msg, WPARAM wparam, LPARAM lparam) { | |
165 return TRUE == PostThreadMessage(thread_id_, msg, wparam, lparam); | |
166 } | |
167 | |
168 } // namespace omaha | |
169 | |
OLD | NEW |