Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 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 | |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 12 | #include <stddef.h> |
| 13 | |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 14 | #include "base/base_export.h" |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 15 | #include "base/macros.h" |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 16 | #include "base/time/time.h" |
| 17 | #include "build/build_config.h" |
| 18 | |
| 19 | #if defined(OS_WIN) |
| 20 | #include <windows.h> |
Jay Civelli | 3a83cdd | 2017-03-22 17:31:44 -0700 | [diff] [blame^] | 21 | #elif defined(OS_MACOSX) |
| 22 | #include <mach/mach_types.h> |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 23 | #elif defined(OS_POSIX) |
| 24 | #include <pthread.h> |
| 25 | #include <unistd.h> |
| 26 | #endif |
| 27 | |
| 28 | namespace base { |
| 29 | |
| 30 | // Used for logging. Always an integer value. |
| 31 | #if defined(OS_WIN) |
| 32 | typedef DWORD PlatformThreadId; |
Jay Civelli | 3a83cdd | 2017-03-22 17:31:44 -0700 | [diff] [blame^] | 33 | #elif defined(OS_MACOSX) |
| 34 | typedef mach_port_t PlatformThreadId; |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 35 | #elif defined(OS_POSIX) |
| 36 | typedef pid_t PlatformThreadId; |
| 37 | #endif |
| 38 | |
| 39 | // Used for thread checking and debugging. |
| 40 | // Meant to be as fast as possible. |
| 41 | // These are produced by PlatformThread::CurrentRef(), and used to later |
| 42 | // check if we are on the same thread or not by using ==. These are safe |
| 43 | // to copy between threads, but can't be copied to another process as they |
| 44 | // have no meaning there. Also, the internal identifier can be re-used |
| 45 | // after a thread dies, so a PlatformThreadRef cannot be reliably used |
| 46 | // to distinguish a new thread from an old, dead thread. |
| 47 | class PlatformThreadRef { |
| 48 | public: |
| 49 | #if defined(OS_WIN) |
| 50 | typedef DWORD RefType; |
| 51 | #elif defined(OS_POSIX) |
| 52 | typedef pthread_t RefType; |
| 53 | #endif |
| 54 | PlatformThreadRef() |
| 55 | : id_(0) { |
| 56 | } |
| 57 | |
| 58 | explicit PlatformThreadRef(RefType id) |
| 59 | : id_(id) { |
| 60 | } |
| 61 | |
| 62 | bool operator==(PlatformThreadRef other) const { |
| 63 | return id_ == other.id_; |
| 64 | } |
| 65 | |
Jay Civelli | 3a83cdd | 2017-03-22 17:31:44 -0700 | [diff] [blame^] | 66 | bool operator!=(PlatformThreadRef other) const { return id_ != other.id_; } |
| 67 | |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 68 | bool is_null() const { |
| 69 | return id_ == 0; |
| 70 | } |
| 71 | private: |
| 72 | RefType id_; |
| 73 | }; |
| 74 | |
| 75 | // Used to operate on threads. |
| 76 | class PlatformThreadHandle { |
| 77 | public: |
| 78 | #if defined(OS_WIN) |
| 79 | typedef void* Handle; |
| 80 | #elif defined(OS_POSIX) |
| 81 | typedef pthread_t Handle; |
| 82 | #endif |
| 83 | |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 84 | PlatformThreadHandle() : handle_(0) {} |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 85 | |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 86 | explicit PlatformThreadHandle(Handle handle) : handle_(handle) {} |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 87 | |
| 88 | bool is_equal(const PlatformThreadHandle& other) const { |
| 89 | return handle_ == other.handle_; |
| 90 | } |
| 91 | |
| 92 | bool is_null() const { |
| 93 | return !handle_; |
| 94 | } |
| 95 | |
| 96 | Handle platform_handle() const { |
| 97 | return handle_; |
| 98 | } |
| 99 | |
| 100 | private: |
| 101 | Handle handle_; |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 102 | }; |
| 103 | |
| 104 | const PlatformThreadId kInvalidThreadId(0); |
| 105 | |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 106 | // Valid values for priority of Thread::Options and SimpleThread::Options, and |
| 107 | // SetCurrentThreadPriority(), listed in increasing order of importance. |
Alex Vakulenko | 4577922 | 2016-03-17 10:36:19 -0700 | [diff] [blame] | 108 | enum class ThreadPriority : int { |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 109 | // Suitable for threads that shouldn't disrupt high priority work. |
| 110 | BACKGROUND, |
| 111 | // Default priority level. |
| 112 | NORMAL, |
| 113 | // Suitable for threads which generate data for the display (at ~60Hz). |
| 114 | DISPLAY, |
| 115 | // Suitable for low-latency, glitch-resistant audio. |
| 116 | REALTIME_AUDIO, |
| 117 | }; |
| 118 | |
| 119 | // A namespace for low-level thread functions. |
| 120 | class BASE_EXPORT PlatformThread { |
| 121 | public: |
| 122 | // Implement this interface to run code on a background thread. Your |
| 123 | // ThreadMain method will be called on the newly created thread. |
| 124 | class BASE_EXPORT Delegate { |
| 125 | public: |
| 126 | virtual void ThreadMain() = 0; |
| 127 | |
| 128 | protected: |
| 129 | virtual ~Delegate() {} |
| 130 | }; |
| 131 | |
| 132 | // Gets the current thread id, which may be useful for logging purposes. |
| 133 | static PlatformThreadId CurrentId(); |
| 134 | |
| 135 | // Gets the current thread reference, which can be used to check if |
| 136 | // we're on the right thread quickly. |
| 137 | static PlatformThreadRef CurrentRef(); |
| 138 | |
| 139 | // Get the handle representing the current thread. On Windows, this is a |
| 140 | // pseudo handle constant which will always represent the thread using it and |
| 141 | // hence should not be shared with other threads nor be used to differentiate |
| 142 | // the current thread from another. |
| 143 | static PlatformThreadHandle CurrentHandle(); |
| 144 | |
| 145 | // Yield the current thread so another thread can be scheduled. |
| 146 | static void YieldCurrentThread(); |
| 147 | |
| 148 | // Sleeps for the specified duration. |
| 149 | static void Sleep(base::TimeDelta duration); |
| 150 | |
Luis Hector Chavez | 0c4f26a | 2016-07-15 16:23:21 -0700 | [diff] [blame] | 151 | // Sets the thread name visible to debuggers/tools. This will try to |
| 152 | // initialize the context for current thread unless it's a WorkerThread. |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 153 | static void SetName(const std::string& name); |
| 154 | |
| 155 | // Gets the thread name, if previously set by SetName. |
| 156 | static const char* GetName(); |
| 157 | |
| 158 | // Creates a new thread. The |stack_size| parameter can be 0 to indicate |
| 159 | // that the default stack size should be used. Upon success, |
| 160 | // |*thread_handle| will be assigned a handle to the newly created thread, |
| 161 | // and |delegate|'s ThreadMain method will be executed on the newly created |
| 162 | // thread. |
| 163 | // NOTE: When you are done with the thread handle, you must call Join to |
| 164 | // release system resources associated with the thread. You must ensure that |
| 165 | // the Delegate object outlives the thread. |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 166 | static bool Create(size_t stack_size, |
| 167 | Delegate* delegate, |
| 168 | PlatformThreadHandle* thread_handle) { |
| 169 | return CreateWithPriority(stack_size, delegate, thread_handle, |
| 170 | ThreadPriority::NORMAL); |
| 171 | } |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 172 | |
| 173 | // CreateWithPriority() does the same thing as Create() except the priority of |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 174 | // the thread is set based on |priority|. |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 175 | static bool CreateWithPriority(size_t stack_size, Delegate* delegate, |
| 176 | PlatformThreadHandle* thread_handle, |
| 177 | ThreadPriority priority); |
| 178 | |
| 179 | // CreateNonJoinable() does the same thing as Create() except the thread |
| 180 | // cannot be Join()'d. Therefore, it also does not output a |
| 181 | // PlatformThreadHandle. |
| 182 | static bool CreateNonJoinable(size_t stack_size, Delegate* delegate); |
| 183 | |
Jay Civelli | 3a83cdd | 2017-03-22 17:31:44 -0700 | [diff] [blame^] | 184 | // CreateNonJoinableWithPriority() does the same thing as CreateNonJoinable() |
| 185 | // except the priority of the thread is set based on |priority|. |
| 186 | static bool CreateNonJoinableWithPriority(size_t stack_size, |
| 187 | Delegate* delegate, |
| 188 | ThreadPriority priority); |
| 189 | |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 190 | // Joins with a thread created via the Create function. This function blocks |
| 191 | // the caller until the designated thread exits. This will invalidate |
| 192 | // |thread_handle|. |
| 193 | static void Join(PlatformThreadHandle thread_handle); |
| 194 | |
Luis Hector Chavez | 0c4f26a | 2016-07-15 16:23:21 -0700 | [diff] [blame] | 195 | // Detaches and releases the thread handle. The thread is no longer joinable |
| 196 | // and |thread_handle| is invalidated after this call. |
| 197 | static void Detach(PlatformThreadHandle thread_handle); |
| 198 | |
Jay Civelli | 3a83cdd | 2017-03-22 17:31:44 -0700 | [diff] [blame^] | 199 | // Returns true if SetCurrentThreadPriority() can be used to increase the |
| 200 | // priority of the current thread. |
| 201 | static bool CanIncreaseCurrentThreadPriority(); |
| 202 | |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 203 | // Toggles the current thread's priority at runtime. A thread may not be able |
| 204 | // to raise its priority back up after lowering it if the process does not |
Alex Vakulenko | 4577922 | 2016-03-17 10:36:19 -0700 | [diff] [blame] | 205 | // have a proper permission, e.g. CAP_SYS_NICE on Linux. A thread may not be |
| 206 | // able to lower its priority back down after raising it to REALTIME_AUDIO. |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 207 | // Since changing other threads' priority is not permitted in favor of |
| 208 | // security, this interface is restricted to change only the current thread |
| 209 | // priority (https://crbug.com/399473). |
| 210 | static void SetCurrentThreadPriority(ThreadPriority priority); |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 211 | |
Alex Vakulenko | 0d205d7 | 2016-01-15 13:02:14 -0800 | [diff] [blame] | 212 | static ThreadPriority GetCurrentThreadPriority(); |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 213 | |
Jay Civelli | 3a83cdd | 2017-03-22 17:31:44 -0700 | [diff] [blame^] | 214 | #if defined(OS_LINUX) |
| 215 | // Toggles a specific thread's priority at runtime. This can be used to |
| 216 | // change the priority of a thread in a different process and will fail |
| 217 | // if the calling process does not have proper permissions. The |
| 218 | // SetCurrentThreadPriority() function above is preferred in favor of |
| 219 | // security but on platforms where sandboxed processes are not allowed to |
| 220 | // change priority this function exists to allow a non-sandboxed process |
| 221 | // to change the priority of sandboxed threads for improved performance. |
| 222 | // Warning: Don't use this for a main thread because that will change the |
| 223 | // whole thread group's (i.e. process) priority. |
| 224 | static void SetThreadPriority(PlatformThreadId thread_id, |
| 225 | ThreadPriority priority); |
| 226 | #endif |
| 227 | |
Daniel Erat | b8cf949 | 2015-07-06 13:18:13 -0600 | [diff] [blame] | 228 | private: |
| 229 | DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); |
| 230 | }; |
| 231 | |
| 232 | } // namespace base |
| 233 | |
| 234 | #endif // BASE_THREADING_PLATFORM_THREAD_H_ |