Hey guys,I just landed r121999, which adds the TaskRunner, SequencedTaskRunner, and SingleThreadTaskRunner interfaces, and makes MessageLoopProxy inherit from SingleThreadTaskRunner.What are these interfaces?In brief:
- TaskRunner has methods for posting tasks, but provides no guarantees as to when, in what order, and on what thread these tasks are run. (Think of a thread pool.)
- SequencedTaskRunner subclasses TaskRunner to provide ordering guarantees, but not thread guarantees. (Think of a sequenced thread pool with a fixed sequence token.)
- SingleThreadTaskRunner subclasses SequencedTaskRunner to guarantee that tasks are run on a single thread. (Think of a message loop.)
Why were they created?The *TaskRunner interfaces grew out of Brett's "The FILE thread is dead" thread, as it became clear that there was a need to decouple task posting from the mechanics of how each task will be run. Also, there's always been a long-standing need to be able to dependency-inject task posting into our various classes and functions, especially for testing: how many times have you struggled with instantiating the right set of MessageLoop, Thread, and BrowserThread objects to be able to unit test your class properly?OK, I'm sold! When can I start using these interfaces?
Right away! There's still plenty of work left to be done (see the next section), but there are some easy things you can do:
- Convert uses of MessageLoopProxy to use SingleThreadTaskRunner, which is a drop-in replacement. Direct use of MessageLoopProxy is now deprecated (except for calling current() to get a pointer to the current one, of course).
- In a similar vein, convert classes that directly use MessageLoop/BrowserThread/etc. to instead use one of the *TaskRunner interfaces via dep-injection. It'll make it way more testable! (Once the test implementations are written, that is.)
If you're feeling adventurous and want to start using non-trivial implementations of the *TaskRunner interfaces right away, shoot me an e-mail with your use case and I'll let you know when there's something ready for you to use.Also, if you feel like helping out, there's a list of bugs below for remaining work. :)When should I use each interface?
- Do you need your tasks to be run on the same thread? Use SingleThreadTaskRunner.
- Do your tasks operate on objects that implement NonThreadSafe or similar? Use SingleThreadTaskRunner.
- Do you need your tasks to be ordered, but don't really care if they're run on different threads? Use SequencedTaskRunner.
- Do you want your tasks to be run on a thread pool, but need them to be ordered? Use SequencedTaskRunner.
- Do you not care how your tasks are ordered or on what thread they're run on? Use TaskRunner.
- Do you want your tasks to be run on a thread pool and don't care about ordering? Use TaskRunner.
What work remains to be done?
- Writing a TaskRunner wrapper around WorkerPool (114329).
- Writing a SequencedTaskRunner wrapper around a SequencedWorkerPool with a fixed sequence token (114330).
- Writing *TaskRunner implementations for testing (114331).
- Writing specification tests for *TaskRunner implementations (114327).
- Writing an equivalent of base::NonThreadSafe for *TaskRunner (114332).
These tasks are marked with the "TaskRunner" label, as well as any other ones I think of later. I plan to start on one of these, but I'll appreciate any help with the others!Comments and questions are welcome.- Fred(Special thanks to darin@ and willchan@ for reviewing the implementation and hashing out the details.)
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
I added another another crbug with the TaskRunner label.
Modify BrowserMessageFilter::OverrideThreadForMessage to return a
TaskRunner instead of a well known BrowserThread::ID
http://code.google.com/p/chromium/issues/detail?id=114474
Cool beans :)
I added another another crbug with the TaskRunner label.
Modify BrowserMessageFilter::OverrideThreadForMessage to return a
TaskRunner instead of a well known BrowserThread::ID
http://code.google.com/p/chromium/issues/detail?id=114474
This is very cool, thanks so much for doing this. I'm sure it'll cleanup our code a lot! Some comments below.On Tue, Feb 14, 2012 at 11:01 PM, Fred Akalin <aka...@chromium.org> wrote:
Hey guys,I just landed r121999, which adds the TaskRunner, SequencedTaskRunner, and SingleThreadTaskRunner interfaces, and makes MessageLoopProxy inherit from SingleThreadTaskRunner.What are these interfaces?In brief:
- TaskRunner has methods for posting tasks, but provides no guarantees as to when, in what order, and on what thread these tasks are run. (Think of a thread pool.)
- SequencedTaskRunner subclasses TaskRunner to provide ordering guarantees, but not thread guarantees. (Think of a sequenced thread pool with a fixed sequence token.)
- SingleThreadTaskRunner subclasses SequencedTaskRunner to guarantee that tasks are run on a single thread. (Think of a message loop.)
Why were they created?The *TaskRunner interfaces grew out of Brett's "The FILE thread is dead" thread, as it became clear that there was a need to decouple task posting from the mechanics of how each task will be run. Also, there's always been a long-standing need to be able to dependency-inject task posting into our various classes and functions, especially for testing: how many times have you struggled with instantiating the right set of MessageLoop, Thread, and BrowserThread objects to be able to unit test your class properly?OK, I'm sold! When can I start using these interfaces?
Right away! There's still plenty of work left to be done (see the next section), but there are some easy things you can do:
- Convert uses of MessageLoopProxy to use SingleThreadTaskRunner, which is a drop-in replacement. Direct use of MessageLoopProxy is now deprecated (except for calling current() to get a pointer to the current one, of course).
- In a similar vein, convert classes that directly use MessageLoop/BrowserThread/etc. to instead use one of the *TaskRunner interfaces via dep-injection. It'll make it way more testable! (Once the test implementations are written, that is.)
I see the benefit if someone is adding a test to a self-contained piece of code to convert that code to use these interfaces. But I'm a little worried that mass conversion of code that uses BrowserThread::PostTask(BrowserThread::X... to then make that object take an interface and change all the dependent code will just be busy work without much benefit, and will just make the code slightly harder to follow (i.e. now pass file/ io interface everywhere).
If you're feeling adventurous and want to start using non-trivial implementations of the *TaskRunner interfaces right away, shoot me an e-mail with your use case and I'll let you know when there's something ready for you to use.
Also, if you feel like helping out, there's a list of bugs below for remaining work. :)When should I use each interface?
- Do you need your tasks to be run on the same thread? Use SingleThreadTaskRunner.
- Do your tasks operate on objects that implement NonThreadSafe or similar? Use SingleThreadTaskRunner.
- Do you need your tasks to be ordered, but don't really care if they're run on different threads? Use SequencedTaskRunner.
- Do you want your tasks to be run on a thread pool, but need them to be ordered? Use SequencedTaskRunner.
I hope no one uses the thread pool in the meantime until this is done!
- Do you not care how your tasks are ordered or on what thread they're run on? Use TaskRunner.
- Do you want your tasks to be run on a thread pool and don't care about ordering? Use TaskRunner.
What work remains to be done?
- Writing a TaskRunner wrapper around WorkerPool (114329).
- Writing a SequencedTaskRunner wrapper around a SequencedWorkerPool with a fixed sequence token (114330).
- Writing *TaskRunner implementations for testing (114331).
- Writing specification tests for *TaskRunner implementations (114327).
- Writing an equivalent of base::NonThreadSafe for *TaskRunner (114332).
These tasks are marked with the "TaskRunner" label, as well as any other ones I think of later. I plan to start on one of these, but I'll appreciate any help with the others!Comments and questions are welcome.- Fred(Special thanks to darin@ and willchan@ for reviewing the implementation and hashing out the details.)
I see the benefit if someone is adding a test to a self-contained piece of code to convert that code to use these interfaces. But I'm a little worried that mass conversion of code that uses BrowserThread::PostTask(BrowserThread::X... to then make that object take an interface and change all the dependent code will just be busy work without much benefit, and will just make the code slightly harder to follow (i.e. now pass file/ io interface everywhere).
I hope no one uses the thread pool in the meantime until this is done!