blob: 8c0d8e4432a5cc8e3a65e256ce675b6571410586 [file] [log] [blame]
Daniel Eratb8cf9492015-07-06 13:18:13 -06001// 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 Vakulenko0d205d72016-01-15 13:02:14 -080012#include <stddef.h>
13
Daniel Eratb8cf9492015-07-06 13:18:13 -060014#include "base/base_export.h"
Alex Vakulenko0d205d72016-01-15 13:02:14 -080015#include "base/macros.h"
Daniel Eratb8cf9492015-07-06 13:18:13 -060016#include "base/time/time.h"
17#include "build/build_config.h"
18
19#if defined(OS_WIN)
20#include <windows.h>
Jay Civelli3a83cdd2017-03-22 17:31:44 -070021#elif defined(OS_MACOSX)
22#include <mach/mach_types.h>
Daniel Eratb8cf9492015-07-06 13:18:13 -060023#elif defined(OS_POSIX)
24#include <pthread.h>
25#include <unistd.h>
26#endif
27
28namespace base {
29
30// Used for logging. Always an integer value.
31#if defined(OS_WIN)
32typedef DWORD PlatformThreadId;
Jay Civelli3a83cdd2017-03-22 17:31:44 -070033#elif defined(OS_MACOSX)
34typedef mach_port_t PlatformThreadId;
Daniel Eratb8cf9492015-07-06 13:18:13 -060035#elif defined(OS_POSIX)
36typedef 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.
47class 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 Civelli3a83cdd2017-03-22 17:31:44 -070066 bool operator!=(PlatformThreadRef other) const { return id_ != other.id_; }
67
Daniel Eratb8cf9492015-07-06 13:18:13 -060068 bool is_null() const {
69 return id_ == 0;
70 }
71 private:
72 RefType id_;
73};
74
75// Used to operate on threads.
76class 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 Vakulenko0d205d72016-01-15 13:02:14 -080084 PlatformThreadHandle() : handle_(0) {}
Daniel Eratb8cf9492015-07-06 13:18:13 -060085
Alex Vakulenko0d205d72016-01-15 13:02:14 -080086 explicit PlatformThreadHandle(Handle handle) : handle_(handle) {}
Daniel Eratb8cf9492015-07-06 13:18:13 -060087
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 Eratb8cf9492015-07-06 13:18:13 -0600102};
103
104const PlatformThreadId kInvalidThreadId(0);
105
Alex Vakulenko0d205d72016-01-15 13:02:14 -0800106// Valid values for priority of Thread::Options and SimpleThread::Options, and
107// SetCurrentThreadPriority(), listed in increasing order of importance.
Alex Vakulenko45779222016-03-17 10:36:19 -0700108enum class ThreadPriority : int {
Daniel Eratb8cf9492015-07-06 13:18:13 -0600109 // 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.
120class 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 Chavez0c4f26a2016-07-15 16:23:21 -0700151 // 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 Eratb8cf9492015-07-06 13:18:13 -0600153 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 Vakulenko0d205d72016-01-15 13:02:14 -0800166 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 Eratb8cf9492015-07-06 13:18:13 -0600172
173 // CreateWithPriority() does the same thing as Create() except the priority of
Alex Vakulenko0d205d72016-01-15 13:02:14 -0800174 // the thread is set based on |priority|.
Daniel Eratb8cf9492015-07-06 13:18:13 -0600175 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 Civelli3a83cdd2017-03-22 17:31:44 -0700184 // 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 Eratb8cf9492015-07-06 13:18:13 -0600190 // 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 Chavez0c4f26a2016-07-15 16:23:21 -0700195 // 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 Civelli3a83cdd2017-03-22 17:31:44 -0700199 // Returns true if SetCurrentThreadPriority() can be used to increase the
200 // priority of the current thread.
201 static bool CanIncreaseCurrentThreadPriority();
202
Alex Vakulenko0d205d72016-01-15 13:02:14 -0800203 // 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 Vakulenko45779222016-03-17 10:36:19 -0700205 // 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 Vakulenko0d205d72016-01-15 13:02:14 -0800207 // 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 Eratb8cf9492015-07-06 13:18:13 -0600211
Alex Vakulenko0d205d72016-01-15 13:02:14 -0800212 static ThreadPriority GetCurrentThreadPriority();
Daniel Eratb8cf9492015-07-06 13:18:13 -0600213
Jay Civelli3a83cdd2017-03-22 17:31:44 -0700214#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 Eratb8cf9492015-07-06 13:18:13 -0600228 private:
229 DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread);
230};
231
232} // namespace base
233
234#endif // BASE_THREADING_PLATFORM_THREAD_H_