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 // Moving |param| prevents an extra AddRef()/Release() pair. |
lazyboy
2017/06/23 20:43:27
Nice, I think you should separate out this std::mo
karandeepb
2017/06/23 22:48:46
Done. Yeah it doesn't compile.
| |
247 thread_->message_loop()->PostTask(FROM_HERE, | |
248 base::Bind(&MyObject::DoSomethingOnAnotherThread, this, | |
249 base::RetainedRef(std::move(param)))); | |
247 } | 250 } |
248 void DoSomething2() { | 251 void DoSomething2() { |
249 SomeParamObject* param = new SomeParamObject; | 252 SomeParamObject* param = new SomeParamObject; |
250 thread_->message_loop()->PostTask(FROM_HERE | 253 thread_->message_loop()->PostTask(FROM_HERE, |
251 base::Bind(&MyObject::DoSomethingOnAnotherThread, this, | 254 base::Bind(&MyObject::DoSomethingOnAnotherThread, this, |
252 make_scoped_refptr(param))); | 255 base::RetainedRef(make_scoped_refptr(param)))); |
253 } | 256 } |
254 // Note how this takes a raw pointer. The important part is that | 257 |
255 // base::Bind() was passed a scoped_refptr; using a scoped_refptr | 258 // Note how this takes a raw pointer. The important part is that using |
lazyboy
2017/06/23 20:43:27
The comment here before was emphasizing that inste
karandeepb
2017/06/23 22:48:46
Done.
| |
256 // here would result in an extra AddRef()/Release() pair. | 259 // base::RetainedRef allows passing a raw pointer when the callback is run |
260 // preventing an extra AddRef()/Release() pair. | |
257 void DoSomethingOnAnotherThread(SomeParamObject* param) { | 261 void DoSomethingOnAnotherThread(SomeParamObject* param) { |
258 ... | 262 ... |
259 } | 263 } |
260 }; | 264 }; |
261 | 265 |
262 If you want to pass the object without taking a reference on it, wrap the | 266 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 | 267 argument with `base::Unretained()`. Again, using this means there are external |
264 guarantees on the lifetime of the object, so tread carefully! | 268 guarantees on the lifetime of the object, so tread carefully! |
265 | 269 |
266 If your object has a non-trivial destructor that needs to run on a specific | 270 If your object has a non-trivial destructor that needs to run on a specific |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
487 int some_input1, int some_input2) { | 491 int some_input1, int some_input2) { |
488 if (request->canceled()) | 492 if (request->canceled()) |
489 return; | 493 return; |
490 | 494 |
491 ... do your processing ... | 495 ... do your processing ... |
492 | 496 |
493 // Execute ForwardResult() like you would do Run() on the base::Callback <>. | 497 // Execute ForwardResult() like you would do Run() on the base::Callback <>. |
494 request->ForwardResult(return_value); | 498 request->ForwardResult(return_value); |
495 } | 499 } |
496 }; | 500 }; |
OLD | NEW |