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