bd8b37f5b5688645c48c2dbb806b6c70febf5f8e
[iec.git] / src / type3_AndroidCloud / anbox-master / external / android-emugl / shared / emugl / common / thread_win32.cpp
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 "emugl/common/thread.h"
16
17 #include "emugl/common/thread_store.h"
18
19 namespace emugl {
20
21 namespace {
22
23 class ScopedLocker {
24 public:
25     ScopedLocker(CRITICAL_SECTION* section) : mSection(section) {
26         EnterCriticalSection(mSection);
27     }
28
29     ~ScopedLocker() {
30         LeaveCriticalSection(mSection);
31     }
32 private:
33     CRITICAL_SECTION* mSection;
34 };
35
36 }  // namespace
37
38 Thread::Thread() :
39     mThread(INVALID_HANDLE_VALUE),
40     mThreadId(0),
41     mExitStatus(0),
42     mIsRunning(false) {
43     InitializeCriticalSection(&mLock);
44 }
45
46 Thread::~Thread() {
47     if(mThread != INVALID_HANDLE_VALUE) {
48         CloseHandle(mThread);
49     }
50     DeleteCriticalSection(&mLock);
51 }
52
53 bool Thread::start() {
54     ScopedLocker locker(&mLock);
55
56     bool ret = true;
57     mIsRunning = true;
58     mThread = CreateThread(NULL, 0, &Thread::thread_main, this, 0, &mThreadId);
59     if (!mThread) {
60         ret = false;
61         mIsRunning = false;
62     }
63     return ret;
64 }
65
66 bool Thread::wait(intptr_t* exitStatus) {
67     {
68         ScopedLocker locker(&mLock);
69         if (!mIsRunning) {
70             // Thread already stopped.
71             if (exitStatus) {
72                 *exitStatus = mExitStatus;
73             }
74             return true;
75         }
76     }
77
78     // NOTE: Do not hold lock during wait to aloow thread_main to
79     // properly update mIsRunning and mExitStatus on thread exit.
80     if (WaitForSingleObject(mThread, INFINITE) == WAIT_FAILED) {
81         return false;
82     }
83
84     if (exitStatus) {
85         ScopedLocker locker(&mLock);
86         *exitStatus = mExitStatus;
87     }
88     return true;
89 }
90
91 bool Thread::tryWait(intptr_t* exitStatus) {
92     ScopedLocker locker(&mLock);
93
94     if (mIsRunning && WaitForSingleObject(mThread, 0) != WAIT_OBJECT_0) {
95         return false;
96     }
97
98     if (exitStatus) {
99         *exitStatus = mExitStatus;
100     }
101     return true;
102 }
103
104 // static
105 DWORD WINAPI Thread::thread_main(void *arg)
106 {
107     Thread* self = reinterpret_cast<Thread*>(arg);
108     intptr_t ret = self->main();
109
110     EnterCriticalSection(&self->mLock);
111     self->mIsRunning = false;
112     self->mExitStatus = ret;
113     LeaveCriticalSection(&self->mLock);
114
115     // Ensure all thread-local values are released for this thread.
116     ::emugl::ThreadStore::OnThreadExit();
117
118     return static_cast<DWORD>(ret);
119 }
120
121 }  // namespace emugl