Home | History | Annotate | Download | only in threading
      1 // Copyright (c) 2011 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 #ifndef BASE_THREAD_H_
      6 #define BASE_THREAD_H_
      7 #pragma once
      8 
      9 #include <string>
     10 
     11 #include "base/base_api.h"
     12 #include "base/message_loop.h"
     13 #include "base/message_loop_proxy.h"
     14 #include "base/threading/platform_thread.h"
     15 
     16 namespace base {
     17 
     18 // A simple thread abstraction that establishes a MessageLoop on a new thread.
     19 // The consumer uses the MessageLoop of the thread to cause code to execute on
     20 // the thread.  When this object is destroyed the thread is terminated.  All
     21 // pending tasks queued on the thread's message loop will run to completion
     22 // before the thread is terminated.
     23 //
     24 // After the thread is stopped, the destruction sequence is:
     25 //
     26 //  (1) Thread::CleanUp()
     27 //  (2) MessageLoop::~MessageLoop
     28 //  (3.b)    MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop
     29 class BASE_API Thread : PlatformThread::Delegate {
     30  public:
     31   struct Options {
     32     Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {}
     33     Options(MessageLoop::Type type, size_t size)
     34         : message_loop_type(type), stack_size(size) {}
     35 
     36     // Specifies the type of message loop that will be allocated on the thread.
     37     MessageLoop::Type message_loop_type;
     38 
     39     // Specifies the maximum stack size that the thread is allowed to use.
     40     // This does not necessarily correspond to the thread's initial stack size.
     41     // A value of 0 indicates that the default maximum should be used.
     42     size_t stack_size;
     43   };
     44 
     45   // Constructor.
     46   // name is a display string to identify the thread.
     47   explicit Thread(const char* name);
     48 
     49   // Destroys the thread, stopping it if necessary.
     50   //
     51   // NOTE: If you are subclassing from Thread, and you wish for your CleanUp
     52   // method to be called, then you need to call Stop() from your destructor.
     53   //
     54   virtual ~Thread();
     55 
     56   // Starts the thread.  Returns true if the thread was successfully started;
     57   // otherwise, returns false.  Upon successful return, the message_loop()
     58   // getter will return non-null.
     59   //
     60   // Note: This function can't be called on Windows with the loader lock held;
     61   // i.e. during a DllMain, global object construction or destruction, atexit()
     62   // callback.
     63   bool Start();
     64 
     65   // Starts the thread. Behaves exactly like Start in addition to allow to
     66   // override the default options.
     67   //
     68   // Note: This function can't be called on Windows with the loader lock held;
     69   // i.e. during a DllMain, global object construction or destruction, atexit()
     70   // callback.
     71   bool StartWithOptions(const Options& options);
     72 
     73   // Signals the thread to exit and returns once the thread has exited.  After
     74   // this method returns, the Thread object is completely reset and may be used
     75   // as if it were newly constructed (i.e., Start may be called again).
     76   //
     77   // Stop may be called multiple times and is simply ignored if the thread is
     78   // already stopped.
     79   //
     80   // NOTE: This method is optional.  It is not strictly necessary to call this
     81   // method as the Thread's destructor will take care of stopping the thread if
     82   // necessary.
     83   //
     84   void Stop();
     85 
     86   // Signals the thread to exit in the near future.
     87   //
     88   // WARNING: This function is not meant to be commonly used. Use at your own
     89   // risk. Calling this function will cause message_loop() to become invalid in
     90   // the near future. This function was created to workaround a specific
     91   // deadlock on Windows with printer worker thread. In any other case, Stop()
     92   // should be used.
     93   //
     94   // StopSoon should not be called multiple times as it is risky to do so. It
     95   // could cause a timing issue in message_loop() access. Call Stop() to reset
     96   // the thread object once it is known that the thread has quit.
     97   void StopSoon();
     98 
     99   // Returns the message loop for this thread.  Use the MessageLoop's
    100   // PostTask methods to execute code on the thread.  This only returns
    101   // non-null after a successful call to Start.  After Stop has been called,
    102   // this will return NULL.
    103   //
    104   // NOTE: You must not call this MessageLoop's Quit method directly.  Use
    105   // the Thread's Stop method instead.
    106   //
    107   MessageLoop* message_loop() const { return message_loop_; }
    108 
    109   // Returns a MessageLoopProxy for this thread.  Use the MessageLoopProxy's
    110   // PostTask methods to execute code on the thread.  This only returns
    111   // non-NULL after a successful call to Start. After Stop has been called,
    112   // this will return NULL. Callers can hold on to this even after the thread
    113   // is gone.
    114   // TODO(sanjeevr): Look into merging MessageLoop and MessageLoopProxy.
    115   scoped_refptr<MessageLoopProxy> message_loop_proxy() {
    116     return message_loop_proxy_;
    117   }
    118 
    119   // Set the name of this thread (for display in debugger too).
    120   const std::string &thread_name() { return name_; }
    121 
    122   // The native thread handle.
    123   PlatformThreadHandle thread_handle() { return thread_; }
    124 
    125   // The thread ID.
    126   PlatformThreadId thread_id() const { return thread_id_; }
    127 
    128   // Returns true if the thread has been started, and not yet stopped.
    129   // When a thread is running, |thread_id_| is a valid id.
    130   bool IsRunning() const { return thread_id_ != kInvalidThreadId; }
    131 
    132  protected:
    133   // Called just prior to starting the message loop
    134   virtual void Init() {}
    135 
    136   // Called to start the message loop
    137   virtual void Run(MessageLoop* message_loop);
    138 
    139   // Called just after the message loop ends
    140   virtual void CleanUp() {}
    141 
    142   // Called after the message loop has been deleted. In general clients
    143   // should prefer to use CleanUp(). This method is used when code needs to
    144   // be run after all of the MessageLoop::DestructionObservers have completed.
    145   virtual void CleanUpAfterMessageLoopDestruction() {}
    146 
    147   static void SetThreadWasQuitProperly(bool flag);
    148   static bool GetThreadWasQuitProperly();
    149 
    150   void set_message_loop(MessageLoop* message_loop) {
    151     message_loop_ = message_loop;
    152   }
    153 
    154  private:
    155   bool thread_was_started() const { return started_; }
    156 
    157   // PlatformThread::Delegate methods:
    158   virtual void ThreadMain();
    159 
    160   // Whether we successfully started the thread.
    161   bool started_;
    162 
    163   // If true, we're in the middle of stopping, and shouldn't access
    164   // |message_loop_|. It may non-NULL and invalid.
    165   bool stopping_;
    166 
    167   // Used to pass data to ThreadMain.
    168   struct StartupData;
    169   StartupData* startup_data_;
    170 
    171   // The thread's handle.
    172   PlatformThreadHandle thread_;
    173 
    174   // The thread's message loop.  Valid only while the thread is alive.  Set
    175   // by the created thread.
    176   MessageLoop* message_loop_;
    177 
    178   // A MessageLoopProxy implementation that targets this thread. This can
    179   // outlive the thread.
    180   scoped_refptr<MessageLoopProxy> message_loop_proxy_;
    181 
    182   // Our thread's ID.
    183   PlatformThreadId thread_id_;
    184 
    185   // The name of the thread.  Used for debugging purposes.
    186   std::string name_;
    187 
    188   friend class ThreadQuitTask;
    189 
    190   DISALLOW_COPY_AND_ASSIGN(Thread);
    191 };
    192 
    193 }  // namespace base
    194 
    195 #endif  // BASE_THREAD_H_
    196