• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
OptionsOptions32     Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {}
OptionsOptions33     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   //
message_loop()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.
message_loop_proxy()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).
thread_name()120   const std::string &thread_name() { return name_; }
121 
122   // The native thread handle.
thread_handle()123   PlatformThreadHandle thread_handle() { return thread_; }
124 
125   // The thread ID.
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.
IsRunning()130   bool IsRunning() const { return thread_id_ != kInvalidThreadId; }
131 
132  protected:
133   // Called just prior to starting the message loop
Init()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
CleanUp()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.
CleanUpAfterMessageLoopDestruction()145   virtual void CleanUpAfterMessageLoopDestruction() {}
146 
147   static void SetThreadWasQuitProperly(bool flag);
148   static bool GetThreadWasQuitProperly();
149 
set_message_loop(MessageLoop * message_loop)150   void set_message_loop(MessageLoop* message_loop) {
151     message_loop_ = message_loop;
152   }
153 
154  private:
thread_was_started()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