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