| 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 |