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 #pragma once
16 
17 #include "aemu/base/Compiler.h"
18 #include "aemu/base/threads/Types.h"
19 #include "aemu/base/synchronization/Lock.h"
20 
21 #ifdef _WIN32
22 #include <windows.h>
23 #else
24 #include <pthread.h>
25 #endif
26 
27 #include <inttypes.h>
28 #include <optional>
29 #include <string>
30 
31 namespace android {
32 namespace base {
33 
34 // Wrapper class for platform-specific threads.
35 // To create your own thread, define a sub-class of emugl::Thread
36 // and override its main() method.
37 //
38 // For example:
39 //
40 //    class MyThread : public emugl::Thread {
41 //    public:
42 //        MyThread() : Thread() {}
43 //
44 //        virtual intptr_t main() {
45 //            ... main thread loop implementation
46 //            return 0;
47 //        }
48 //    };
49 //
50 //    ...
51 //
52 //    // Create new instance, but does not start it.
53 //    MyThread* thread = new MyThread();
54 //
55 //    // Start the thread.
56 //    thread->start();
57 //
58 //    // Wait for thread completion, and gets result into |exitStatus|.
59 //    int exitStatus;
60 //    thread->wait(&exitStatus);
61 //
62 class Thread {
63     DISALLOW_COPY_ASSIGN_AND_MOVE(Thread);
64 
65 public:
66     // Public constructor.
67     Thread(ThreadFlags flags = ThreadFlags::MaskSignals, int stackSize = 0,
68            std::optional<std::string> name = std::nullopt);
69 
70     // Virtual destructor.
71     virtual ~Thread();
72 
73     // Override this method in your own thread sub-classes. This will
74     // be called when start() is invoked on the Thread instance.
75     virtual intptr_t main() = 0;
76 
77     // Override this if you need to execute some code after thread has
78     // exited main() and is guaranteed not to access any of its members.
79     // E.g. if you need to delete a thread object from the same thread
80     // it has created
onExit()81     virtual void onExit() {}
82 
83     // Start a thread instance. Return true on success, false otherwise
84     // (e.g. if the thread was already started or terminated).
85     bool start();
86 
87     // Wait for thread termination and retrieve exist status into
88     // |*exitStatus|. Return true on success, false otherwise.
89     // NOTE: |exitStatus| can be NULL.
90     virtual bool  wait(intptr_t *exitStatus = nullptr);
91 
92     // Check whether a thread has terminated. On success, return true
93     // and sets |*exitStatus|. On failure, return false.
94     // NOTE: |exitStatus| can be NULL.
95     bool tryWait(intptr_t *exitStatus);
96 
97     // Mask all signals for the current thread
98     // This is needed for the qemu guest to run properly
99     // NB: noop for Win32
100     static void maskAllSignals();
101 
102     // Sleep for |n| milliseconds
103     static void sleepMs(unsigned n);
104 
105     // Sleep for |n| microseconds
106     static void sleepUs(unsigned n);
107 
108     // Yield the remaining part of current thread's CPU time slice to another
109     // thread that's ready to run.
110     static void yield();
111 
112 protected:
113     std::optional<std::string> mNameOpt = std::nullopt;
114 
115 private:
116 #ifdef _WIN32
117     static DWORD WINAPI thread_main(void* arg);
118 
119     HANDLE mThread = nullptr;
120 #else // !WIN32
121     static void* thread_main(void* arg);
122 
123     pthread_t mThread;
124 #endif
125     Lock mLock;
126     // Access guarded by |mLock|.
127     intptr_t mExitStatus = 0;
128     int mStackSize;
129     const ThreadFlags mFlags;
130     bool mStarted = false;
131     // Access guarded by |mLock|.
132     bool mFinished = false;
133 #ifndef _WIN32
134     // Posix-only, remember if we've joined our non-detached thread already.
135     bool mJoined = false;
136 #endif
137 };
138 
139 // Helper function to obtain a printable id for the current thread.
140 unsigned long getCurrentThreadId();
141 
142 // Helper function to set/get/ui thread status.
143 void setUiThreadId(unsigned long id);
144 bool isRunningInUiThread();
145 
146 // Subclass of Thread covering interruptible threads.
147 class InterruptibleThread : public Thread {
148     DISALLOW_COPY_ASSIGN_AND_MOVE(InterruptibleThread);
149 public:
150     // Public constructor.
151     InterruptibleThread(ThreadFlags flags = ThreadFlags::MaskSignals, int stackSize = 0) :
Thread(flags,stackSize)152         Thread(flags, stackSize) { }
153 
154     virtual void interrupt() = 0;
155 };
156 
157 }  // namespace base
158 }  // namespace android
159