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