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