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