15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WARNING: You should *NOT* be using this class directly. PlatformThread is 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the low-level platform-specific abstraction to the OS's threading interface. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You should instead be using a message-loop driven Thread, see thread.h. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_THREADING_PLATFORM_THREAD_H_ 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_THREADING_PLATFORM_THREAD_H_ 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Used for logging. Always an integer value. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef DWORD PlatformThreadId; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef pid_t PlatformThreadId; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Used for thread checking and debugging. 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Meant to be as fast as possible. 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// These are produced by PlatformThread::CurrentRef(), and used to later 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// check if we are on the same thread or not by using ==. These are safe 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to copy between threads, but can't be copied to another process as they 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// have no meaning there. Also, the internal identifier can be re-used 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// after a thread dies, so a PlatformThreadRef cannot be reliably used 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to distinguish a new thread from an old, dead thread. 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class PlatformThreadRef { 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_WIN) 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef DWORD RefType; 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#elif defined(OS_POSIX) 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef pthread_t RefType; 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PlatformThreadRef() 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : id_(0) { 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) explicit PlatformThreadRef(RefType id) 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : id_(id) { 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool operator==(PlatformThreadRef other) const { 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return id_ == other.id_; 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool is_null() const { 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return id_ == 0; 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RefType id_; 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Used to operate on threads. 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class PlatformThreadHandle { 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN) 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) typedef void* Handle; 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#elif defined(OS_POSIX) 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) typedef pthread_t Handle; 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PlatformThreadHandle() 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : handle_(0), 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) id_(0) { 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) explicit PlatformThreadHandle(Handle handle) 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : handle_(handle), 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) id_(0) { 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PlatformThreadHandle(Handle handle, 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PlatformThreadId id) 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : handle_(handle), 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) id_(id) { 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_equal(const PlatformThreadHandle& other) const { 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return handle_ == other.handle_; 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_null() const { 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return !handle_; 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Handle platform_handle() const { 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return handle_; 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) friend class PlatformThread; 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Handle handle_; 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PlatformThreadId id_; 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const PlatformThreadId kInvalidThreadId(0); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Valid values for SetThreadPriority() 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ThreadPriority{ 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kThreadPriority_Normal, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Suitable for low-latency, glitch-resistant audio. 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kThreadPriority_RealtimeAudio, 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Suitable for threads which generate data for the display (at ~60Hz). 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kThreadPriority_Display, 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Suitable for threads that shouldn't disrupt high priority work. 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kThreadPriority_Background 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A namespace for low-level thread functions. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT PlatformThread { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Implement this interface to run code on a background thread. Your 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ThreadMain method will be called on the newly created thread. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class BASE_EXPORT Delegate { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ThreadMain() = 0; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Delegate() {} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the current thread id, which may be useful for logging purposes. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static PlatformThreadId CurrentId(); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Gets the current thread reference, which can be used to check if 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // we're on the right thread quickly. 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static PlatformThreadRef CurrentRef(); 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Get the current handle. 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static PlatformThreadHandle CurrentHandle(); 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Yield the current thread so another thread can be scheduled. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void YieldCurrentThread(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sleeps for the specified duration. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void Sleep(base::TimeDelta duration); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the thread name visible to debuggers/tools. This has no effect 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise. This name pointer is not copied internally. Thus, it must stay 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid until the thread ends. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void SetName(const char* name); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the thread name, if previously set by SetName. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char* GetName(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a new thread. The |stack_size| parameter can be 0 to indicate 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the default stack size should be used. Upon success, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |*thread_handle| will be assigned a handle to the newly created thread, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and |delegate|'s ThreadMain method will be executed on the newly created 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: When you are done with the thread handle, you must call Join to 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release system resources associated with the thread. You must ensure that 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the Delegate object outlives the thread. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool Create(size_t stack_size, Delegate* delegate, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PlatformThreadHandle* thread_handle); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CreateWithPriority() does the same thing as Create() except the priority of 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the thread is set based on |priority|. Can be used in place of Create() 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // followed by SetThreadPriority(). SetThreadPriority() has not been 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // implemented on the Linux platform yet, this is the only way to get a high 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // priority thread on Linux. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool CreateWithPriority(size_t stack_size, Delegate* delegate, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PlatformThreadHandle* thread_handle, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadPriority priority); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CreateNonJoinable() does the same thing as Create() except the thread 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cannot be Join()'d. Therefore, it also does not output a 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PlatformThreadHandle. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool CreateNonJoinable(size_t stack_size, Delegate* delegate); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Joins with a thread created via the Create function. This function blocks 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the caller until the designated thread exits. This will invalidate 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |thread_handle|. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void Join(PlatformThreadHandle thread_handle); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void SetThreadPriority(PlatformThreadHandle handle, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadPriority priority); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_THREADING_PLATFORM_THREAD_H_ 201