1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // WARNING: You should *NOT* be using this class directly. PlatformThread is 6 // the low-level platform-specific abstraction to the OS's threading interface. 7 // You should instead be using a message-loop driven Thread, see thread.h. 8 9 #ifndef BASE_THREADING_PLATFORM_THREAD_H_ 10 #define BASE_THREADING_PLATFORM_THREAD_H_ 11 12 #include <stddef.h> 13 14 #include "base/base_export.h" 15 #include "base/macros.h" 16 #include "base/time/time.h" 17 #include "build/build_config.h" 18 19 #if defined(OS_WIN) 20 #include <windows.h> 21 #elif defined(OS_POSIX) 22 #include <pthread.h> 23 #include <unistd.h> 24 #endif 25 26 namespace base { 27 28 // Used for logging. Always an integer value. 29 #if defined(OS_WIN) 30 typedef DWORD PlatformThreadId; 31 #elif defined(OS_POSIX) 32 typedef pid_t PlatformThreadId; 33 #endif 34 35 // Used for thread checking and debugging. 36 // Meant to be as fast as possible. 37 // These are produced by PlatformThread::CurrentRef(), and used to later 38 // check if we are on the same thread or not by using ==. These are safe 39 // to copy between threads, but can't be copied to another process as they 40 // have no meaning there. Also, the internal identifier can be re-used 41 // after a thread dies, so a PlatformThreadRef cannot be reliably used 42 // to distinguish a new thread from an old, dead thread. 43 class PlatformThreadRef { 44 public: 45 #if defined(OS_WIN) 46 typedef DWORD RefType; 47 #elif defined(OS_POSIX) 48 typedef pthread_t RefType; 49 #endif PlatformThreadRef()50 PlatformThreadRef() 51 : id_(0) { 52 } 53 PlatformThreadRef(RefType id)54 explicit PlatformThreadRef(RefType id) 55 : id_(id) { 56 } 57 58 bool operator==(PlatformThreadRef other) const { 59 return id_ == other.id_; 60 } 61 is_null()62 bool is_null() const { 63 return id_ == 0; 64 } 65 private: 66 RefType id_; 67 }; 68 69 // Used to operate on threads. 70 class PlatformThreadHandle { 71 public: 72 #if defined(OS_WIN) 73 typedef void* Handle; 74 #elif defined(OS_POSIX) 75 typedef pthread_t Handle; 76 #endif 77 PlatformThreadHandle()78 PlatformThreadHandle() : handle_(0) {} 79 PlatformThreadHandle(Handle handle)80 explicit PlatformThreadHandle(Handle handle) : handle_(handle) {} 81 is_equal(const PlatformThreadHandle & other)82 bool is_equal(const PlatformThreadHandle& other) const { 83 return handle_ == other.handle_; 84 } 85 is_null()86 bool is_null() const { 87 return !handle_; 88 } 89 platform_handle()90 Handle platform_handle() const { 91 return handle_; 92 } 93 94 private: 95 Handle handle_; 96 }; 97 98 const PlatformThreadId kInvalidThreadId(0); 99 100 // Valid values for priority of Thread::Options and SimpleThread::Options, and 101 // SetCurrentThreadPriority(), listed in increasing order of importance. 102 enum class ThreadPriority : int { 103 // Suitable for threads that shouldn't disrupt high priority work. 104 BACKGROUND, 105 // Default priority level. 106 NORMAL, 107 // Suitable for threads which generate data for the display (at ~60Hz). 108 DISPLAY, 109 // Suitable for low-latency, glitch-resistant audio. 110 REALTIME_AUDIO, 111 }; 112 113 // A namespace for low-level thread functions. 114 class BASE_EXPORT PlatformThread { 115 public: 116 // Implement this interface to run code on a background thread. Your 117 // ThreadMain method will be called on the newly created thread. 118 class BASE_EXPORT Delegate { 119 public: 120 virtual void ThreadMain() = 0; 121 122 protected: ~Delegate()123 virtual ~Delegate() {} 124 }; 125 126 // Gets the current thread id, which may be useful for logging purposes. 127 static PlatformThreadId CurrentId(); 128 129 // Gets the current thread reference, which can be used to check if 130 // we're on the right thread quickly. 131 static PlatformThreadRef CurrentRef(); 132 133 // Get the handle representing the current thread. On Windows, this is a 134 // pseudo handle constant which will always represent the thread using it and 135 // hence should not be shared with other threads nor be used to differentiate 136 // the current thread from another. 137 static PlatformThreadHandle CurrentHandle(); 138 139 // Yield the current thread so another thread can be scheduled. 140 static void YieldCurrentThread(); 141 142 // Sleeps for the specified duration. 143 static void Sleep(base::TimeDelta duration); 144 145 // Sets the thread name visible to debuggers/tools. This will try to 146 // initialize the context for current thread unless it's a WorkerThread. 147 static void SetName(const std::string& name); 148 149 // Gets the thread name, if previously set by SetName. 150 static const char* GetName(); 151 152 // Creates a new thread. The |stack_size| parameter can be 0 to indicate 153 // that the default stack size should be used. Upon success, 154 // |*thread_handle| will be assigned a handle to the newly created thread, 155 // and |delegate|'s ThreadMain method will be executed on the newly created 156 // thread. 157 // NOTE: When you are done with the thread handle, you must call Join to 158 // release system resources associated with the thread. You must ensure that 159 // the Delegate object outlives the thread. Create(size_t stack_size,Delegate * delegate,PlatformThreadHandle * thread_handle)160 static bool Create(size_t stack_size, 161 Delegate* delegate, 162 PlatformThreadHandle* thread_handle) { 163 return CreateWithPriority(stack_size, delegate, thread_handle, 164 ThreadPriority::NORMAL); 165 } 166 167 // CreateWithPriority() does the same thing as Create() except the priority of 168 // the thread is set based on |priority|. 169 static bool CreateWithPriority(size_t stack_size, Delegate* delegate, 170 PlatformThreadHandle* thread_handle, 171 ThreadPriority priority); 172 173 // CreateNonJoinable() does the same thing as Create() except the thread 174 // cannot be Join()'d. Therefore, it also does not output a 175 // PlatformThreadHandle. 176 static bool CreateNonJoinable(size_t stack_size, Delegate* delegate); 177 178 // Joins with a thread created via the Create function. This function blocks 179 // the caller until the designated thread exits. This will invalidate 180 // |thread_handle|. 181 static void Join(PlatformThreadHandle thread_handle); 182 183 // Detaches and releases the thread handle. The thread is no longer joinable 184 // and |thread_handle| is invalidated after this call. 185 static void Detach(PlatformThreadHandle thread_handle); 186 187 // Toggles the current thread's priority at runtime. A thread may not be able 188 // to raise its priority back up after lowering it if the process does not 189 // have a proper permission, e.g. CAP_SYS_NICE on Linux. A thread may not be 190 // able to lower its priority back down after raising it to REALTIME_AUDIO. 191 // Since changing other threads' priority is not permitted in favor of 192 // security, this interface is restricted to change only the current thread 193 // priority (https://crbug.com/399473). 194 static void SetCurrentThreadPriority(ThreadPriority priority); 195 196 static ThreadPriority GetCurrentThreadPriority(); 197 198 private: 199 DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); 200 }; 201 202 } // namespace base 203 204 #endif // BASE_THREADING_PLATFORM_THREAD_H_ 205