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