• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2014 The Android Open Source Project
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 #include "base/Thread.h"
16 
17 #include <assert.h>
18 
19 namespace android {
20 namespace base {
21 
Thread(ThreadFlags flags,int stackSize)22 Thread::Thread(ThreadFlags flags, int stackSize)
23     : mStackSize(stackSize), mFlags(flags) {}
24 
~Thread()25 Thread::~Thread() {
26     if (mThread) {
27         assert(!mStarted || mFinished);
28         CloseHandle(mThread);
29     }
30 }
31 
start()32 bool Thread::start() {
33     if (mStarted) {
34         return false;
35     }
36 
37     bool ret = true;
38     mStarted = true;
39     DWORD threadId = 0;
40     mThread = CreateThread(NULL, mStackSize, &Thread::thread_main, this, 0,
41                            &threadId);
42     if (!mThread) {
43         // don't reset mStarted: we're artifically limiting the user's
44         // ability to retry the failed starts here.
45         ret = false;
46         mFinished = true;
47     }
48     return ret;
49 }
50 
wait(intptr_t * exitStatus)51 bool Thread::wait(intptr_t* exitStatus) {
52     if (!mStarted || (mFlags & ThreadFlags::Detach) != ThreadFlags::NoFlags) {
53         return false;
54     }
55 
56     // NOTE: Do not hold lock during wait to allow thread_main to
57     // properly update mIsRunning and mFinished on thread exit.
58     if (WaitForSingleObject(mThread, INFINITE) == WAIT_FAILED) {
59         return false;
60     }
61 
62     if (exitStatus) {
63         *exitStatus = mExitStatus;
64     }
65     return true;
66 }
67 
tryWait(intptr_t * exitStatus)68 bool Thread::tryWait(intptr_t* exitStatus) {
69     if (!mStarted || (mFlags & ThreadFlags::Detach) != ThreadFlags::NoFlags) {
70         return false;
71     }
72 
73     AutoLock locker(mLock);
74     if (!mFinished || WaitForSingleObject(mThread, 0) != WAIT_OBJECT_0) {
75         return false;
76     }
77 
78     if (exitStatus) {
79         *exitStatus = mExitStatus;
80     }
81     return true;
82 }
83 
84 // static
thread_main(void * arg)85 DWORD WINAPI Thread::thread_main(void* arg) {
86     {
87         // no need to call maskAllSignals() here: we know
88         // that on Windows it's a noop
89         Thread* self = reinterpret_cast<Thread*>(arg);
90         auto ret = self->main();
91 
92         {
93             AutoLock lock(self->mLock);
94             self->mFinished = true;
95             self->mExitStatus = ret;
96         }
97 
98         self->onExit();
99         // |self| is not valid beyond this point
100     }
101 
102     // This return value is ignored.
103     return 0;
104 }
105 
106 // static
maskAllSignals()107 void Thread::maskAllSignals() {
108     // no such thing as signal in Windows
109 }
110 
111 // static
sleepMs(unsigned n)112 void Thread::sleepMs(unsigned n) {
113     ::Sleep(n);
114 }
115 
116 // static
sleepUs(unsigned n)117 void Thread::sleepUs(unsigned n) {
118     // Hehe
119     ::Sleep(n / 1000);
120 }
121 
122 // static
yield()123 void Thread::yield() {
124     if (!::SwitchToThread()) {
125         ::Sleep(0);
126     }
127 }
128 
getCurrentThreadId()129 unsigned long getCurrentThreadId() {
130     return static_cast<unsigned long>(GetCurrentThreadId());
131 }
132 
133 static unsigned long sUiThreadId = 0;
setUiThreadId(unsigned long id)134 void setUiThreadId(unsigned long id) {
135     sUiThreadId = id;
136 
137 }
138 
isRunningInUiThread()139 bool isRunningInUiThread() {
140     if (!sUiThreadId) return false;
141     return sUiThreadId == getCurrentThreadId();
142 }
143 
144 }  // namespace base
145 }  // namespace android
146