OLD | NEW |
1 # Threading | 1 # Threading |
2 | 2 |
3 [TOC] | 3 [TOC] |
4 | 4 |
5 ## Overview | 5 ## Overview |
6 | 6 |
7 Chromium is a very multithreaded product. We try to keep the UI as responsive as | 7 Chromium is a very multithreaded product. We try to keep the UI as responsive as |
8 possible, and this means not blocking the UI thread with any blocking I/O or | 8 possible, and this means not blocking the UI thread with any blocking I/O or |
9 other expensive operations. Our approach is to use message passing as the way of | 9 other expensive operations. Our approach is to use message passing as the way of |
10 communicating between threads. We discourage locking and threadsafe | 10 communicating between threads. We discourage locking and threadsafe |
11 objects. Instead, objects live on only one thread, we pass messages between | 11 objects. Instead, objects live on only one thread, we pass messages between |
12 threads for communication, and we use callback interfaces (implemented by | 12 threads for communication, and we use callback interfaces (implemented by |
13 message passing) for most cross-thread requests. | 13 message passing) for most cross-thread requests. |
14 | 14 |
15 The `Thread` object is defined in | 15 The `Thread` object is defined in |
16 [`base/threading/thread.h`](https://cs.chromium.org/chromium/src/base/threading/
thread.h). | 16 [`base/threading/thread.h`](https://cs.chromium.org/chromium/src/base/threading/
thread.h). |
17 In general you should probably use one of the existing threads described below | 17 In general you should probably use one of the existing threads described below |
18 rather than make new ones. We already have a lot of threads that are difficult | 18 rather than make new ones. We already have a lot of threads that are difficult |
19 to keep track of. Each thread has a `MessageLoop` (see | 19 to keep track of. Each thread has a `MessageLoop` (see |
20 [`base/message_loop/message_loop.h`](https://cs.chromium.org/chromium/src/base/m
essage_loop/message_loop.h) | 20 [`base/message_loop/message_loop.h`](https://cs.chromium.org/chromium/src/base/m
essage_loop/message_loop.h) |
21 that processes messages for that thread. You can get the message loop for a | 21 that processes messages for that thread. You can get the message loop for a |
22 thread using the `Thread.message_loop()` function. More details about | 22 thread using the `Thread.message_loop()` function. More details about |
23 `MessageLoop` can be found in | 23 `MessageLoop` can be found in |
24 [Anatomy of Chromium MessageLoop](https://docs.google.com/document/d/1_pJUHO3f3V
yRSQjEhKVvUU7NzCyuTCQshZvbWeQiCXU/view#). | 24 [Anatomy of Chromium MessageLoop](https://docs.google.com/document/d/1_pJUHO3f3V
yRSQjEhKVvUU7NzCyuTCQshZvbWeQiCXU/view#). |
25 | 25 |
26 ## Existing threads | 26 ## Existing threads |
27 | 27 |
28 Most threads are managed by the BrowserProcess object, which acts as the service | 28 Most threads are managed by the BrowserProcess object, which acts as the service |
29 manager for the main "browser" process. By default, everything happens on the UI | 29 manager for the main "browser" process. By default, everything happens on the UI |
30 thread. We have pushed certain classes of processing into these other | 30 thread. We have pushed certain classes of processing into these other |
31 threads. It has getters for the following threads: | 31 threads. It has getters for the following threads: |
32 | 32 |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 raw pointer with `make_scoped_refptr()`: | 235 raw pointer with `make_scoped_refptr()`: |
236 | 236 |
237 class SomeParamObject : public base::RefCountedThreadSafe<SomeParamObject> { | 237 class SomeParamObject : public base::RefCountedThreadSafe<SomeParamObject> { |
238 ... | 238 ... |
239 }; | 239 }; |
240 | 240 |
241 class MyObject : public base::RefCountedThreadSafe<MyObject> { | 241 class MyObject : public base::RefCountedThreadSafe<MyObject> { |
242 public: | 242 public: |
243 void DoSomething() { | 243 void DoSomething() { |
244 scoped_refptr<SomeParamObject> param(new SomeParamObject); | 244 scoped_refptr<SomeParamObject> param(new SomeParamObject); |
245 thread_->message_loop()->PostTask(FROM_HERE | 245 |
246 base::Bind(&MyObject::DoSomethingOnAnotherThread, this, param)); | 246 // Without RetainedRef, the scoped_refptr would try to implicitly |
| 247 // convert to a raw pointer and fail compilation. |
| 248 thread_->message_loop()->PostTask(FROM_HERE, |
| 249 base::Bind(&MyObject::DoSomethingOnAnotherThread, this, |
| 250 base::RetainedRef(param))); |
247 } | 251 } |
| 252 |
248 void DoSomething2() { | 253 void DoSomething2() { |
249 SomeParamObject* param = new SomeParamObject; | 254 SomeParamObject* param = new SomeParamObject; |
250 thread_->message_loop()->PostTask(FROM_HERE | 255 thread_->message_loop()->PostTask(FROM_HERE, |
251 base::Bind(&MyObject::DoSomethingOnAnotherThread, this, | 256 base::Bind(&MyObject::DoSomethingOnAnotherThread, this, |
252 make_scoped_refptr(param))); | 257 base::RetainedRef(make_scoped_refptr(param)))); |
253 } | 258 } |
| 259 |
| 260 void DoSomething3() { |
| 261 scoped_refptr<SomeParamObject> param(new SomeParamObject); |
| 262 |
| 263 // Moving |param| prevents an extra AddRef()/Release() pair. |
| 264 thread_->message_loop()->PostTask(FROM_HERE, |
| 265 base::Bind(&MyObject::DoSomethingOnAnotherThread, this, |
| 266 base::RetainedRef(std::move(param)))); |
| 267 } |
| 268 |
254 // Note how this takes a raw pointer. The important part is that | 269 // Note how this takes a raw pointer. The important part is that |
255 // base::Bind() was passed a scoped_refptr; using a scoped_refptr | 270 // base::Bind() was passed a scoped_refptr; using a scoped_refptr |
256 // here would result in an extra AddRef()/Release() pair. | 271 // here would result in an extra AddRef()/Release() pair. |
257 void DoSomethingOnAnotherThread(SomeParamObject* param) { | 272 void DoSomethingOnAnotherThread(SomeParamObject* param) { |
258 ... | 273 ... |
259 } | 274 } |
260 }; | 275 }; |
261 | 276 |
262 If you want to pass the object without taking a reference on it, wrap the | 277 If you want to pass the object without taking a reference on it, wrap the |
263 argument with `base::Unretained()`. Again, using this means there are external | 278 argument with `base::Unretained()`. Again, using this means there are external |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 int some_input1, int some_input2) { | 502 int some_input1, int some_input2) { |
488 if (request->canceled()) | 503 if (request->canceled()) |
489 return; | 504 return; |
490 | 505 |
491 ... do your processing ... | 506 ... do your processing ... |
492 | 507 |
493 // Execute ForwardResult() like you would do Run() on the base::Callback
<>. | 508 // Execute ForwardResult() like you would do Run() on the base::Callback
<>. |
494 request->ForwardResult(return_value); | 509 request->ForwardResult(return_value); |
495 } | 510 } |
496 }; | 511 }; |
OLD | NEW |