thread.h revision 868fa2fe829687343ffae624259930155e16dbd8
15b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// Use of this source code is governed by a BSD-style license that can be
35b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// found in the LICENSE file.
45b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
55b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#ifndef BASE_THREADING_THREAD_H_
65b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#define BASE_THREADING_THREAD_H_
75b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
85b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <string>
95b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
105b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "base/base_export.h"
115b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "base/message_loop.h"
125b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "base/message_loop/message_loop_proxy.h"
135b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "base/threading/platform_thread.h"
145b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
155b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovnamespace base {
165b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
175b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// A simple thread abstraction that establishes a MessageLoop on a new thread.
185b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// The consumer uses the MessageLoop of the thread to cause code to execute on
195b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// the thread.  When this object is destroyed the thread is terminated.  All
205b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// pending tasks queued on the thread's message loop will run to completion
215b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// before the thread is terminated.
225b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov//
235b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// WARNING! SUBCLASSES MUST CALL Stop() IN THEIR DESTRUCTORS!  See ~Thread().
245b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov//
255b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov// After the thread is stopped, the destruction sequence is:
265b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov//
275b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov//  (1) Thread::CleanUp()
285b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov//  (2) MessageLoop::~MessageLoop
295b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov//  (3.b)    MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop
305b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovclass BASE_EXPORT Thread : PlatformThread::Delegate {
315b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov public:
325b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  struct Options {
335b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {}
345b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    Options(MessageLoop::Type type, size_t size)
355b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov        : message_loop_type(type), stack_size(size) {}
365b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
375b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    // Specifies the type of message loop that will be allocated on the thread.
385b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    MessageLoop::Type message_loop_type;
395b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
405b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    // Specifies the maximum stack size that the thread is allowed to use.
415b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    // This does not necessarily correspond to the thread's initial stack size.
425b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    // A value of 0 indicates that the default maximum should be used.
435b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    size_t stack_size;
445b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  };
455b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
465b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Constructor.
475b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // name is a display string to identify the thread.
485b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  explicit Thread(const char* name);
495b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
505b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Destroys the thread, stopping it if necessary.
515b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  //
525b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // NOTE: ALL SUBCLASSES OF Thread MUST CALL Stop() IN THEIR DESTRUCTORS (or
535b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // guarantee Stop() is explicitly called before the subclass is destroyed).
545b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // This is required to avoid a data race between the destructor modifying the
555b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // vtable, and the thread's ThreadMain calling the virtual method Run().  It
565b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // also ensures that the CleanUp() virtual method is called on the subclass
575b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // before it is destructed.
585b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  virtual ~Thread();
595b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
605b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#if defined(OS_WIN)
615b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Causes the thread to initialize COM.  This must be called before calling
625b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Start() or StartWithOptions().  If |use_mta| is false, the thread is also
635b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // started with a TYPE_UI message loop.  It is an error to call
64580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // init_com_with_mta(false) and then StartWithOptions() with any message loop
655b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // type other than TYPE_UI.
66580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  void init_com_with_mta(bool use_mta) {
67580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    DCHECK(!started_);
68580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    com_status_ = use_mta ? MTA : STA;
69580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  }
70580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif
71580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
725b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Starts the thread.  Returns true if the thread was successfully started;
735b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // otherwise, returns false.  Upon successful return, the message_loop()
74580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // getter will return non-null.
75580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  //
76580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // Note: This function can't be called on Windows with the loader lock held;
775b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // i.e. during a DllMain, global object construction or destruction, atexit()
785b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // callback.
795b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  bool Start();
805b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
815b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Starts the thread. Behaves exactly like Start in addition to allow to
825b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // override the default options.
83580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  //
845b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Note: This function can't be called on Windows with the loader lock held;
852716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov  // i.e. during a DllMain, global object construction or destruction, atexit()
862716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov  // callback.
872716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov  bool StartWithOptions(const Options& options);
882716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov
892716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov  // Signals the thread to exit and returns once the thread has exited.  After
902716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov  // this method returns, the Thread object is completely reset and may be used
912716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov  // as if it were newly constructed (i.e., Start may be called again).
922716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov  //
932716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov  // Stop may be called multiple times and is simply ignored if the thread is
94580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // already stopped.
955b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  //
96580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // NOTE: If you are a consumer of Thread, it is not necessary to call this
97580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // before deleting your Thread objects, as the destructor will do it.
985b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // IF YOU ARE A SUBCLASS OF Thread, YOU MUST CALL THIS IN YOUR DESTRUCTOR.
99580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  void Stop();
100580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
101580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // Signals the thread to exit in the near future.
1025b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  //
1035b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // WARNING: This function is not meant to be commonly used. Use at your own
1045b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // risk. Calling this function will cause message_loop() to become invalid in
1055b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // the near future. This function was created to workaround a specific
1065b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // deadlock on Windows with printer worker thread. In any other case, Stop()
1075b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // should be used.
1085b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  //
1095b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // StopSoon should not be called multiple times as it is risky to do so. It
1105b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // could cause a timing issue in message_loop() access. Call Stop() to reset
1115b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // the thread object once it is known that the thread has quit.
1125b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  void StopSoon();
1135b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1145b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Returns the message loop for this thread.  Use the MessageLoop's
1155b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // PostTask methods to execute code on the thread.  This only returns
1165b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // non-null after a successful call to Start.  After Stop has been called,
1175b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // this will return NULL.
118600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  //
119600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // NOTE: You must not call this MessageLoop's Quit method directly.  Use
120600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // the Thread's Stop method instead.
121600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  //
122600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  MessageLoop* message_loop() const { return message_loop_; }
123600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
124600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Returns a MessageLoopProxy for this thread.  Use the MessageLoopProxy's
125600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // PostTask methods to execute code on the thread.  This only returns
126600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // non-NULL after a successful call to Start. After Stop has been called,
1275b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // this will return NULL. Callers can hold on to this even after the thread
1285b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // is gone.
1295b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  scoped_refptr<MessageLoopProxy> message_loop_proxy() const {
1305b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    return message_loop_ ? message_loop_->message_loop_proxy() : NULL;
131600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  }
132600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
1335b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Returns the name of this thread (for display in debugger too).
134600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  const std::string& thread_name() const { return name_; }
1355b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
136600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // The native thread handle.
137600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  PlatformThreadHandle thread_handle() { return thread_; }
138580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
1395b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // The thread ID.
1405b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  PlatformThreadId thread_id() const { return thread_id_; }
141600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
142600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Returns true if the thread has been started, and not yet stopped.
143600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  bool IsRunning() const;
144600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
145600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Sets the thread priority. The thread must already be started.
146600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  void SetPriority(ThreadPriority priority);
147600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
148600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov protected:
149600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Called just prior to starting the message loop
1505b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  virtual void Init() {}
1515b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1525b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Called to start the message loop
1535b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  virtual void Run(MessageLoop* message_loop);
1545b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1555b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Called just after the message loop ends
1565b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  virtual void CleanUp() {}
1575b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1585b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  static void SetThreadWasQuitProperly(bool flag);
1595b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  static bool GetThreadWasQuitProperly();
1605b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1615b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  void set_message_loop(MessageLoop* message_loop) {
16207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov    message_loop_ = message_loop;
16307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  }
1645b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1655b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov private:
1665b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#if defined(OS_WIN)
1675b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  enum ComStatus {
1685b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    NONE,
169    STA,
170    MTA,
171  };
172#endif
173
174  // PlatformThread::Delegate methods:
175  virtual void ThreadMain() OVERRIDE;
176
177#if defined(OS_WIN)
178  // Whether this thread needs to initialize COM, and if so, in what mode.
179  ComStatus com_status_;
180#endif
181
182  // Whether we successfully started the thread.
183  bool started_;
184
185  // If true, we're in the middle of stopping, and shouldn't access
186  // |message_loop_|. It may non-NULL and invalid.
187  bool stopping_;
188
189  // True while inside of Run().
190  bool running_;
191
192  // Used to pass data to ThreadMain.
193  struct StartupData;
194  StartupData* startup_data_;
195
196  // The thread's handle.
197  PlatformThreadHandle thread_;
198
199  // The thread's message loop.  Valid only while the thread is alive.  Set
200  // by the created thread.
201  MessageLoop* message_loop_;
202
203  // Our thread's ID.
204  PlatformThreadId thread_id_;
205
206  // The name of the thread.  Used for debugging purposes.
207  std::string name_;
208
209  friend void ThreadQuitHelper();
210
211  DISALLOW_COPY_AND_ASSIGN(Thread);
212};
213
214}  // namespace base
215
216#endif  // BASE_THREADING_THREAD_H_
217