Home | History | Annotate | Download | only in threading
      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 <stddef.h>
     13 
     14 #include "base/base_export.h"
     15 #include "base/macros.h"
     16 #include "base/time/time.h"
     17 #include "build/build_config.h"
     18 
     19 #if defined(OS_WIN)
     20 #include <windows.h>
     21 #elif defined(OS_MACOSX)
     22 #include <mach/mach_types.h>
     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;
     33 #elif defined(OS_MACOSX)
     34 typedef mach_port_t PlatformThreadId;
     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 
     66   bool operator!=(PlatformThreadRef other) const { return id_ != other.id_; }
     67 
     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 
     84   PlatformThreadHandle() : handle_(0) {}
     85 
     86   explicit PlatformThreadHandle(Handle handle) : handle_(handle) {}
     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_;
    102 };
    103 
    104 const PlatformThreadId kInvalidThreadId(0);
    105 
    106 // Valid values for priority of Thread::Options and SimpleThread::Options, and
    107 // SetCurrentThreadPriority(), listed in increasing order of importance.
    108 enum class ThreadPriority : int {
    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 
    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.
    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.
    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   }
    172 
    173   // CreateWithPriority() does the same thing as Create() except the priority of
    174   // the thread is set based on |priority|.
    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 
    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 
    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 
    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 
    199   // Returns true if SetCurrentThreadPriority() can be used to increase the
    200   // priority of the current thread.
    201   static bool CanIncreaseCurrentThreadPriority();
    202 
    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
    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.
    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);
    211 
    212   static ThreadPriority GetCurrentThreadPriority();
    213 
    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 
    228  private:
    229   DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread);
    230 };
    231 
    232 }  // namespace base
    233 
    234 #endif  // BASE_THREADING_PLATFORM_THREAD_H_
    235