browser_thread.h revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2012 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 CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_H_ 6#define CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_H_ 7 8#include <string> 9 10#include "base/basictypes.h" 11#include "base/callback.h" 12#include "base/location.h" 13#include "base/message_loop_proxy.h" 14#include "base/task_runner_util.h" 15#include "base/time.h" 16#include "content/common/content_export.h" 17 18#if defined(UNIT_TEST) 19#include "base/logging.h" 20#endif // UNIT_TEST 21 22namespace base { 23class MessageLoop; 24class SequencedWorkerPool; 25class Thread; 26} 27 28namespace content { 29 30class BrowserThreadDelegate; 31class BrowserThreadImpl; 32 33/////////////////////////////////////////////////////////////////////////////// 34// BrowserThread 35// 36// Utility functions for threads that are known by a browser-wide 37// name. For example, there is one IO thread for the entire browser 38// process, and various pieces of code find it useful to retrieve a 39// pointer to the IO thread's message loop. 40// 41// Invoke a task by thread ID: 42// 43// BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task); 44// 45// The return value is false if the task couldn't be posted because the target 46// thread doesn't exist. If this could lead to data loss, you need to check the 47// result and restructure the code to ensure it doesn't occur. 48// 49// This class automatically handles the lifetime of different threads. 50// It's always safe to call PostTask on any thread. If it's not yet created, 51// the task is deleted. There are no race conditions. If the thread that the 52// task is posted to is guaranteed to outlive the current thread, then no locks 53// are used. You should never need to cache pointers to MessageLoops, since 54// they're not thread safe. 55class CONTENT_EXPORT BrowserThread { 56 public: 57 // An enumeration of the well-known threads. 58 // NOTE: threads must be listed in the order of their life-time, with each 59 // thread outliving every other thread below it. 60 enum ID { 61 // The main thread in the browser. 62 UI, 63 64 // This is the thread that interacts with the database. 65 DB, 66 67 // This is the "main" thread for WebKit within the browser process when 68 // NOT in --single-process mode. 69 // Deprecated: Do not design new code to use this thread; see 70 // http://crbug.com/106839 71 WEBKIT_DEPRECATED, 72 73 // This is the thread that interacts with the file system. 74 FILE, 75 76 // Used for file system operations that block user interactions. 77 // Responsiveness of this thread affect users. 78 FILE_USER_BLOCKING, 79 80 // Used to launch and terminate Chrome processes. 81 PROCESS_LAUNCHER, 82 83 // This is the thread to handle slow HTTP cache operations. 84 CACHE, 85 86 // This is the thread that processes IPC and network messages. 87 IO, 88 89 // NOTE: do not add new threads here that are only used by a small number of 90 // files. Instead you should just use a Thread class and pass its 91 // MessageLoopProxy around. Named threads there are only for threads that 92 // are used in many places. 93 94 // This identifier does not represent a thread. Instead it counts the 95 // number of well-known threads. Insert new well-known threads before this 96 // identifier. 97 ID_COUNT 98 }; 99 100 // These are the same methods in message_loop.h, but are guaranteed to either 101 // get posted to the MessageLoop if it's still alive, or be deleted otherwise. 102 // They return true iff the thread existed and the task was posted. Note that 103 // even if the task is posted, there's no guarantee that it will run, since 104 // the target thread may already have a Quit message in its queue. 105 static bool PostTask(ID identifier, 106 const tracked_objects::Location& from_here, 107 const base::Closure& task); 108 static bool PostDelayedTask(ID identifier, 109 const tracked_objects::Location& from_here, 110 const base::Closure& task, 111 base::TimeDelta delay); 112 static bool PostNonNestableTask(ID identifier, 113 const tracked_objects::Location& from_here, 114 const base::Closure& task); 115 static bool PostNonNestableDelayedTask( 116 ID identifier, 117 const tracked_objects::Location& from_here, 118 const base::Closure& task, 119 base::TimeDelta delay); 120 121 static bool PostTaskAndReply( 122 ID identifier, 123 const tracked_objects::Location& from_here, 124 const base::Closure& task, 125 const base::Closure& reply); 126 127 template <typename ReturnType, typename ReplyArgType> 128 static bool PostTaskAndReplyWithResult( 129 ID identifier, 130 const tracked_objects::Location& from_here, 131 const base::Callback<ReturnType(void)>& task, 132 const base::Callback<void(ReplyArgType)>& reply) { 133 scoped_refptr<base::MessageLoopProxy> message_loop_proxy = 134 GetMessageLoopProxyForThread(identifier); 135 return base::PostTaskAndReplyWithResult( 136 message_loop_proxy.get(), from_here, task, reply); 137 } 138 139 template <class T> 140 static bool DeleteSoon(ID identifier, 141 const tracked_objects::Location& from_here, 142 const T* object) { 143 return GetMessageLoopProxyForThread(identifier)->DeleteSoon( 144 from_here, object); 145 } 146 147 template <class T> 148 static bool ReleaseSoon(ID identifier, 149 const tracked_objects::Location& from_here, 150 const T* object) { 151 return GetMessageLoopProxyForThread(identifier)->ReleaseSoon( 152 from_here, object); 153 } 154 155 // Simplified wrappers for posting to the blocking thread pool. Use this 156 // for doing things like blocking I/O. 157 // 158 // The first variant will run the task in the pool with no sequencing 159 // semantics, so may get run in parallel with other posted tasks. The second 160 // variant will all post a task with no sequencing semantics, and will post a 161 // reply task to the origin TaskRunner upon completion. The third variant 162 // provides sequencing between tasks with the same sequence token name. 163 // 164 // These tasks are guaranteed to run before shutdown. 165 // 166 // If you need to provide different shutdown semantics (like you have 167 // something slow and noncritical that doesn't need to block shutdown), 168 // or you want to manually provide a sequence token (which saves a map 169 // lookup and is guaranteed unique without you having to come up with a 170 // unique string), you can access the sequenced worker pool directly via 171 // GetBlockingPool(). 172 static bool PostBlockingPoolTask(const tracked_objects::Location& from_here, 173 const base::Closure& task); 174 static bool PostBlockingPoolTaskAndReply( 175 const tracked_objects::Location& from_here, 176 const base::Closure& task, 177 const base::Closure& reply); 178 static bool PostBlockingPoolSequencedTask( 179 const std::string& sequence_token_name, 180 const tracked_objects::Location& from_here, 181 const base::Closure& task); 182 183 // Returns the thread pool used for blocking file I/O. Use this object to 184 // perform random blocking operations such as file writes or querying the 185 // Windows registry. 186 static base::SequencedWorkerPool* GetBlockingPool(); 187 188 // Callable on any thread. Returns whether the given ID corresponds to a well 189 // known thread. 190 static bool IsWellKnownThread(ID identifier); 191 192 // Callable on any thread. Returns whether you're currently on a particular 193 // thread. 194 static bool CurrentlyOn(ID identifier); 195 196 // Callable on any thread. Returns whether the threads message loop is valid. 197 // If this returns false it means the thread is in the process of shutting 198 // down. 199 static bool IsMessageLoopValid(ID identifier); 200 201 // If the current message loop is one of the known threads, returns true and 202 // sets identifier to its ID. Otherwise returns false. 203 static bool GetCurrentThreadIdentifier(ID* identifier); 204 205 // Callers can hold on to a refcounted MessageLoopProxy beyond the lifetime 206 // of the thread. 207 static scoped_refptr<base::MessageLoopProxy> GetMessageLoopProxyForThread( 208 ID identifier); 209 210 // Returns a pointer to the thread's message loop, which will become 211 // invalid during shutdown, so you probably shouldn't hold onto it. 212 // 213 // This must not be called before the thread is started, or after 214 // the thread is stopped, or it will DCHECK. 215 // 216 // Ownership remains with the BrowserThread implementation, so you 217 // must not delete the pointer. 218 static base::MessageLoop* UnsafeGetMessageLoopForThread(ID identifier); 219 220 // Sets the delegate for the specified BrowserThread. 221 // 222 // Only one delegate may be registered at a time. Delegates may be 223 // unregistered by providing a NULL pointer. 224 // 225 // If the caller unregisters a delegate before CleanUp has been 226 // called, it must perform its own locking to ensure the delegate is 227 // not deleted while unregistering. 228 static void SetDelegate(ID identifier, BrowserThreadDelegate* delegate); 229 230 // Use these templates in conjuction with RefCountedThreadSafe when you want 231 // to ensure that an object is deleted on a specific thread. This is needed 232 // when an object can hop between threads (i.e. IO -> FILE -> IO), and thread 233 // switching delays can mean that the final IO tasks executes before the FILE 234 // task's stack unwinds. This would lead to the object destructing on the 235 // FILE thread, which often is not what you want (i.e. to unregister from 236 // NotificationService, to notify other objects on the creating thread etc). 237 template<ID thread> 238 struct DeleteOnThread { 239 template<typename T> 240 static void Destruct(const T* x) { 241 if (CurrentlyOn(thread)) { 242 delete x; 243 } else { 244 if (!DeleteSoon(thread, FROM_HERE, x)) { 245#if defined(UNIT_TEST) 246 // Only logged under unit testing because leaks at shutdown 247 // are acceptable under normal circumstances. 248 LOG(ERROR) << "DeleteSoon failed on thread " << thread; 249#endif // UNIT_TEST 250 } 251 } 252 } 253 }; 254 255 // Sample usage: 256 // class Foo 257 // : public base::RefCountedThreadSafe< 258 // Foo, BrowserThread::DeleteOnIOThread> { 259 // 260 // ... 261 // private: 262 // friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>; 263 // friend class base::DeleteHelper<Foo>; 264 // 265 // ~Foo(); 266 struct DeleteOnUIThread : public DeleteOnThread<UI> { }; 267 struct DeleteOnIOThread : public DeleteOnThread<IO> { }; 268 struct DeleteOnFileThread : public DeleteOnThread<FILE> { }; 269 struct DeleteOnDBThread : public DeleteOnThread<DB> { }; 270 271 private: 272 friend class BrowserThreadImpl; 273 274 BrowserThread() {} 275 DISALLOW_COPY_AND_ASSIGN(BrowserThread); 276}; 277 278} // namespace content 279 280#endif // CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_H_ 281