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_POSIX)
     22 #include <pthread.h>
     23 #include <unistd.h>
     24 #endif
     25 
     26 namespace base {
     27 
     28 // Used for logging. Always an integer value.
     29 #if defined(OS_WIN)
     30 typedef DWORD PlatformThreadId;
     31 #elif defined(OS_POSIX)
     32 typedef pid_t PlatformThreadId;
     33 #endif
     34 
     35 // Used for thread checking and debugging.
     36 // Meant to be as fast as possible.
     37 // These are produced by PlatformThread::CurrentRef(), and used to later
     38 // check if we are on the same thread or not by using ==. These are safe
     39 // to copy between threads, but can't be copied to another process as they
     40 // have no meaning there. Also, the internal identifier can be re-used
     41 // after a thread dies, so a PlatformThreadRef cannot be reliably used
     42 // to distinguish a new thread from an old, dead thread.
     43 class PlatformThreadRef {
     44  public:
     45 #if defined(OS_WIN)
     46   typedef DWORD RefType;
     47 #elif defined(OS_POSIX)
     48   typedef pthread_t RefType;
     49 #endif
     50   PlatformThreadRef()
     51       : id_(0) {
     52   }
     53 
     54   explicit PlatformThreadRef(RefType id)
     55       : id_(id) {
     56   }
     57 
     58   bool operator==(PlatformThreadRef other) const {
     59     return id_ == other.id_;
     60   }
     61 
     62   bool is_null() const {
     63     return id_ == 0;
     64   }
     65  private:
     66   RefType id_;
     67 };
     68 
     69 // Used to operate on threads.
     70 class PlatformThreadHandle {
     71  public:
     72 #if defined(OS_WIN)
     73   typedef void* Handle;
     74 #elif defined(OS_POSIX)
     75   typedef pthread_t Handle;
     76 #endif
     77 
     78   PlatformThreadHandle() : handle_(0) {}
     79 
     80   explicit PlatformThreadHandle(Handle handle) : handle_(handle) {}
     81 
     82   bool is_equal(const PlatformThreadHandle& other) const {
     83     return handle_ == other.handle_;
     84   }
     85 
     86   bool is_null() const {
     87     return !handle_;
     88   }
     89 
     90   Handle platform_handle() const {
     91     return handle_;
     92   }
     93 
     94  private:
     95   Handle handle_;
     96 };
     97 
     98 const PlatformThreadId kInvalidThreadId(0);
     99 
    100 // Valid values for priority of Thread::Options and SimpleThread::Options, and
    101 // SetCurrentThreadPriority(), listed in increasing order of importance.
    102 enum class ThreadPriority {
    103   // Suitable for threads that shouldn't disrupt high priority work.
    104   BACKGROUND,
    105   // Default priority level.
    106   NORMAL,
    107   // Suitable for threads which generate data for the display (at ~60Hz).
    108   DISPLAY,
    109   // Suitable for low-latency, glitch-resistant audio.
    110   REALTIME_AUDIO,
    111 };
    112 
    113 // A namespace for low-level thread functions.
    114 class BASE_EXPORT PlatformThread {
    115  public:
    116   // Implement this interface to run code on a background thread.  Your
    117   // ThreadMain method will be called on the newly created thread.
    118   class BASE_EXPORT Delegate {
    119    public:
    120     virtual void ThreadMain() = 0;
    121 
    122    protected:
    123     virtual ~Delegate() {}
    124   };
    125 
    126   // Gets the current thread id, which may be useful for logging purposes.
    127   static PlatformThreadId CurrentId();
    128 
    129   // Gets the current thread reference, which can be used to check if
    130   // we're on the right thread quickly.
    131   static PlatformThreadRef CurrentRef();
    132 
    133   // Get the handle representing the current thread. On Windows, this is a
    134   // pseudo handle constant which will always represent the thread using it and
    135   // hence should not be shared with other threads nor be used to differentiate
    136   // the current thread from another.
    137   static PlatformThreadHandle CurrentHandle();
    138 
    139   // Yield the current thread so another thread can be scheduled.
    140   static void YieldCurrentThread();
    141 
    142   // Sleeps for the specified duration.
    143   static void Sleep(base::TimeDelta duration);
    144 
    145   // Sets the thread name visible to debuggers/tools. This has no effect
    146   // otherwise.
    147   static void SetName(const std::string& name);
    148 
    149   // Gets the thread name, if previously set by SetName.
    150   static const char* GetName();
    151 
    152   // Creates a new thread.  The |stack_size| parameter can be 0 to indicate
    153   // that the default stack size should be used.  Upon success,
    154   // |*thread_handle| will be assigned a handle to the newly created thread,
    155   // and |delegate|'s ThreadMain method will be executed on the newly created
    156   // thread.
    157   // NOTE: When you are done with the thread handle, you must call Join to
    158   // release system resources associated with the thread.  You must ensure that
    159   // the Delegate object outlives the thread.
    160   static bool Create(size_t stack_size,
    161                      Delegate* delegate,
    162                      PlatformThreadHandle* thread_handle) {
    163     return CreateWithPriority(stack_size, delegate, thread_handle,
    164                               ThreadPriority::NORMAL);
    165   }
    166 
    167   // CreateWithPriority() does the same thing as Create() except the priority of
    168   // the thread is set based on |priority|.
    169   static bool CreateWithPriority(size_t stack_size, Delegate* delegate,
    170                                  PlatformThreadHandle* thread_handle,
    171                                  ThreadPriority priority);
    172 
    173   // CreateNonJoinable() does the same thing as Create() except the thread
    174   // cannot be Join()'d.  Therefore, it also does not output a
    175   // PlatformThreadHandle.
    176   static bool CreateNonJoinable(size_t stack_size, Delegate* delegate);
    177 
    178   // Joins with a thread created via the Create function.  This function blocks
    179   // the caller until the designated thread exits.  This will invalidate
    180   // |thread_handle|.
    181   static void Join(PlatformThreadHandle thread_handle);
    182 
    183   // Toggles the current thread's priority at runtime. A thread may not be able
    184   // to raise its priority back up after lowering it if the process does not
    185   // have a proper permission, e.g. CAP_SYS_NICE on Linux.
    186   // Since changing other threads' priority is not permitted in favor of
    187   // security, this interface is restricted to change only the current thread
    188   // priority (https://crbug.com/399473).
    189   static void SetCurrentThreadPriority(ThreadPriority priority);
    190 
    191   static ThreadPriority GetCurrentThreadPriority();
    192 
    193  private:
    194   DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread);
    195 };
    196 
    197 }  // namespace base
    198 
    199 #endif  // BASE_THREADING_PLATFORM_THREAD_H_
    200