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 "base/base_export.h" 13 #include "base/basictypes.h" 14 #include "base/time/time.h" 15 #include "build/build_config.h" 16 17 #if defined(OS_WIN) 18 #include <windows.h> 19 #elif defined(OS_POSIX) 20 #include <pthread.h> 21 #include <unistd.h> 22 #endif 23 24 namespace base { 25 26 // Used for logging. Always an integer value. 27 #if defined(OS_WIN) 28 typedef DWORD PlatformThreadId; 29 #elif defined(OS_POSIX) 30 typedef pid_t PlatformThreadId; 31 #endif 32 33 // Used for thread checking and debugging. 34 // Meant to be as fast as possible. 35 // These are produced by PlatformThread::CurrentRef(), and used to later 36 // check if we are on the same thread or not by using ==. These are safe 37 // to copy between threads, but can't be copied to another process as they 38 // have no meaning there. Also, the internal identifier can be re-used 39 // after a thread dies, so a PlatformThreadRef cannot be reliably used 40 // to distinguish a new thread from an old, dead thread. 41 class PlatformThreadRef { 42 public: 43 #if defined(OS_WIN) 44 typedef DWORD RefType; 45 #elif defined(OS_POSIX) 46 typedef pthread_t RefType; 47 #endif PlatformThreadRef()48 PlatformThreadRef() 49 : id_(0) { 50 } 51 PlatformThreadRef(RefType id)52 explicit PlatformThreadRef(RefType id) 53 : id_(id) { 54 } 55 56 bool operator==(PlatformThreadRef other) const { 57 return id_ == other.id_; 58 } 59 is_null()60 bool is_null() const { 61 return id_ == 0; 62 } 63 private: 64 RefType id_; 65 }; 66 67 // Used to operate on threads. 68 class PlatformThreadHandle { 69 public: 70 #if defined(OS_WIN) 71 typedef void* Handle; 72 #elif defined(OS_POSIX) 73 typedef pthread_t Handle; 74 #endif 75 PlatformThreadHandle()76 PlatformThreadHandle() 77 : handle_(0), 78 id_(0) { 79 } 80 PlatformThreadHandle(Handle handle)81 explicit PlatformThreadHandle(Handle handle) 82 : handle_(handle), 83 id_(0) { 84 } 85 PlatformThreadHandle(Handle handle,PlatformThreadId id)86 PlatformThreadHandle(Handle handle, 87 PlatformThreadId id) 88 : handle_(handle), 89 id_(id) { 90 } 91 is_equal(const PlatformThreadHandle & other)92 bool is_equal(const PlatformThreadHandle& other) const { 93 return handle_ == other.handle_; 94 } 95 is_null()96 bool is_null() const { 97 return !handle_; 98 } 99 platform_handle()100 Handle platform_handle() const { 101 return handle_; 102 } 103 104 private: 105 friend class PlatformThread; 106 107 Handle handle_; 108 PlatformThreadId id_; 109 }; 110 111 const PlatformThreadId kInvalidThreadId(0); 112 113 // Valid values for SetThreadPriority() 114 enum ThreadPriority{ 115 kThreadPriority_Normal, 116 // Suitable for low-latency, glitch-resistant audio. 117 kThreadPriority_RealtimeAudio, 118 // Suitable for threads which generate data for the display (at ~60Hz). 119 kThreadPriority_Display, 120 // Suitable for threads that shouldn't disrupt high priority work. 121 kThreadPriority_Background 122 }; 123 124 // A namespace for low-level thread functions. 125 class BASE_EXPORT PlatformThread { 126 public: 127 // Implement this interface to run code on a background thread. Your 128 // ThreadMain method will be called on the newly created thread. 129 class BASE_EXPORT Delegate { 130 public: 131 virtual void ThreadMain() = 0; 132 133 protected: ~Delegate()134 virtual ~Delegate() {} 135 }; 136 137 // Gets the current thread id, which may be useful for logging purposes. 138 static PlatformThreadId CurrentId(); 139 140 // Gets the current thread reference, which can be used to check if 141 // we're on the right thread quickly. 142 static PlatformThreadRef CurrentRef(); 143 144 // Get the current handle. 145 static PlatformThreadHandle CurrentHandle(); 146 147 // Yield the current thread so another thread can be scheduled. 148 static void YieldCurrentThread(); 149 150 // Sleeps for the specified duration. 151 static void Sleep(base::TimeDelta duration); 152 153 // Sets the thread name visible to debuggers/tools. This has no effect 154 // otherwise. This name pointer is not copied internally. Thus, it must stay 155 // valid until the thread ends. 156 static void SetName(const char* name); 157 158 // Gets the thread name, if previously set by SetName. 159 static const char* GetName(); 160 161 // Creates a new thread. The |stack_size| parameter can be 0 to indicate 162 // that the default stack size should be used. Upon success, 163 // |*thread_handle| will be assigned a handle to the newly created thread, 164 // and |delegate|'s ThreadMain method will be executed on the newly created 165 // thread. 166 // NOTE: When you are done with the thread handle, you must call Join to 167 // release system resources associated with the thread. You must ensure that 168 // the Delegate object outlives the thread. 169 static bool Create(size_t stack_size, Delegate* delegate, 170 PlatformThreadHandle* thread_handle); 171 172 // CreateWithPriority() does the same thing as Create() except the priority of 173 // the thread is set based on |priority|. Can be used in place of Create() 174 // followed by SetThreadPriority(). SetThreadPriority() has not been 175 // implemented on the Linux platform yet, this is the only way to get a high 176 // priority thread on Linux. 177 static bool CreateWithPriority(size_t stack_size, Delegate* delegate, 178 PlatformThreadHandle* thread_handle, 179 ThreadPriority priority); 180 181 // CreateNonJoinable() does the same thing as Create() except the thread 182 // cannot be Join()'d. Therefore, it also does not output a 183 // PlatformThreadHandle. 184 static bool CreateNonJoinable(size_t stack_size, Delegate* delegate); 185 186 // Joins with a thread created via the Create function. This function blocks 187 // the caller until the designated thread exits. This will invalidate 188 // |thread_handle|. 189 static void Join(PlatformThreadHandle thread_handle); 190 191 static void SetThreadPriority(PlatformThreadHandle handle, 192 ThreadPriority priority); 193 194 private: 195 DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); 196 }; 197 198 } // namespace base 199 200 #endif // BASE_THREADING_PLATFORM_THREAD_H_ 201