OLD | NEW |
---|---|
(Empty) | |
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 CONTENT_COMMON_SEQUENCED_WORKER_POOL_H_ | |
6 #define CONTENT_COMMON_SEQUENCED_WORKER_POOL_H_ | |
7 #pragma once | |
8 | |
9 #include "base/callback.h" | |
10 #include "base/memory/linked_ptr.h" | |
11 #include "base/memory/ref_counted.h" | |
12 #include "base/tracked_objects.h" | |
13 | |
14 // A worker thread pool that enforces ordering between sets of tasks. It also | |
15 // allows you to specify what should happen to your tasks on shutdown. | |
16 // | |
17 // To enforce ordering, get a unique sequence token from the pool and post all | |
18 // tasks you want to order with the token. All tasks with the same token are | |
19 // guaranteed to execute serially, though not necessarily on the same thread. | |
20 // | |
21 // Example: | |
22 // SequencedWorkerPool::SequenceToken token = pool.GetSequenceToken(); | |
23 // pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN, | |
24 // FROM_HERE, base::Bind(...)); | |
jar (doing other things)
2011/10/29 02:37:14
Although I have yet to figure out how to do it, I
| |
25 // pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN, | |
26 // FROM_HERE, base::Bind(...)); | |
27 // | |
28 // You can also post tasks to the pool without ordering using PostWorkerTask. | |
29 // These will be executed in an unspecified order. The order of execution | |
30 // between tasks with different sequence tokens is also unspecified. | |
31 // | |
32 // This class is designed to be leaked on shutdown to allow the | |
33 // CONTINUE_ON_SHUTDOWN behavior to be implemented. To enforce the | |
34 // BLOCK_SHUTDOWN behavior, you must call Shutdown() which will wait until | |
jar (doing other things)
2011/10/29 02:37:14
I think we want most folks to not block shutdown.
| |
35 // the necessary tasks have completed. | |
36 // | |
37 // Implementation note: This does not use a base::WorkerPool since that does | |
38 // not enforce shutdown semantics or allow us to specify how many worker | |
39 // threads to run. For the typical use case of random background work, we don't | |
40 // necessarily want to be super aggressive about creating threads. | |
41 class SequencedWorkerPool { | |
42 public: | |
43 // Defines what should happen to a task posted to the worker pool on shutdown. | |
44 enum WorkerShutdown { | |
45 // Tasks posted with this mode which have not run at shutdown will be | |
46 // deleted rather than run, and any tasks with this mode running at | |
47 // shutdown will be ignored (the worker thread will not be joined). | |
48 // | |
49 // This option provides a nice way to post stuff you don't want blocking | |
50 // shutdown. For example, you might be doing a slow DNS lookup and if it's | |
51 // blocked on the OS, you may not want to stop shutdown, since the result | |
52 // doesn't really matter at that point. | |
53 // | |
54 // However, you need to be very careful what you do in your callback when | |
55 // you use this option. Since the thread will continue to run until the OS | |
56 // terminates the process, the app can be in the process of tearing down | |
57 // when you're running. This means any singletons or global objects you | |
58 // use may suddenly become invalid out from under you. For this reason, | |
59 // it's best to use this only for slow but simple operations like the DNS | |
60 // example. | |
61 CONTINUE_ON_SHUTDOWN, | |
62 | |
63 // Tasks posted with this mode that have not started executing at shutdown | |
64 // will be deleted rather than executed. However, tasks already in progress | |
65 // will be completed. | |
66 SKIP_ON_SHUTDOWN, | |
jar (doing other things)
2011/10/29 02:37:14
This is a confusing distinction with CONTINUE_ON_S
brettw
2011/10/29 05:31:18
Yes. SKIP_ON_SHUTDOWN is the default for the curre
| |
67 | |
68 // Tasks posted with this mode will block browser shutdown until they're | |
69 // executed. Since this can have significant performance implications, use | |
70 // sparingly. | |
jar (doing other things)
2011/10/29 02:37:14
What happens if a BLOCK_SHUTDOWN task appears in l
brettw
2011/10/29 05:31:18
Interesting point, I missed that. I'll move the sh
| |
71 // | |
72 // Generally, this should be used only for user data, for example, a task | |
73 // writing a preference file. | |
74 // | |
75 // If a task is posted during shutdown, it will not get run since the | |
76 // workers may already be stopped. In this case, the post operation will | |
77 // fail (return false) and the task will be deleted. | |
jar (doing other things)
2011/10/29 02:37:14
Hmm.. that sounds like a confusing or racy definit
brettw
2011/10/29 05:31:18
I didn't know how else to define this. I wanted a
| |
78 BLOCK_SHUTDOWN, | |
79 }; | |
80 | |
81 // Opaque identifier that defines sequencing of tasks posted to the worker | |
82 // pool. See NewSequenceToken(). | |
83 class SequenceToken { | |
84 public: | |
85 SequenceToken() : id_(0) {} | |
86 ~SequenceToken() {} | |
87 | |
88 private: | |
89 friend SequencedWorkerPool; | |
90 | |
91 SequenceToken(int id) : id_(id) {} | |
92 | |
93 int id_; | |
jar (doing other things)
2011/10/29 02:37:14
This probably needs to be an atomic, or more likel
brettw
2011/10/29 05:31:18
This isn't changed, it's the value returned to the
| |
94 }; | |
95 | |
96 // Allows tests to perform certain actions. | |
97 class TestingObserver { | |
98 public: | |
99 virtual void WillWaitForShutdown() = 0; | |
100 }; | |
101 | |
102 SequencedWorkerPool(size_t max_threads); | |
103 ~SequencedWorkerPool(); | |
104 | |
105 // Returns a unique token that can be used to sequence tasks posted to | |
106 // PostSequencedWorkerTask(). Valid tokens are alwys nonzero. | |
jar (doing other things)
2011/10/29 02:37:14
nit: alwys
| |
107 SequenceToken GetSequenceToken(); | |
108 | |
109 // Posts the given task for execution in the worker pool. Tasks posted with | |
110 // this function will execute in an unspecified order on a background thread. | |
111 // Returns true if the task was posted. If your tasks have ordering | |
112 // requirements, see PostSequencedWorkerTask(). | |
113 // | |
114 // Returns true if the task was posted successfully. This may fail during | |
115 // shutdown regardless of the specified ShutdownBehavior. | |
116 bool PostWorkerTask(WorkerShutdown shutdown_behavior, | |
117 const tracked_objects::Location& from_here, | |
118 const base::Closure& task); | |
119 | |
120 // Like PostWorkerTask above, but provides sequencing semantics. This means | |
121 // that tasks posted with the same sequence token (see GetSequenceToken()) | |
122 // are guaranteed to execute in order. This is useful in cases where you're | |
123 // doing operations that may depend on previous ones, like appending to a | |
124 // file. | |
125 // | |
126 // Returns true if the task was posted successfully. This may fail during | |
127 // shutdown regardless of the specified ShutdownBehavior. | |
jar (doing other things)
2011/10/29 02:37:14
I guess it is good that you have weasel words. Ca
brettw
2011/10/29 05:31:18
See discussion above, I don't think we can do bett
| |
128 bool PostSequencedWorkerTask(SequenceToken sequence_token, | |
129 WorkerShutdown shutdown_behavior, | |
130 const tracked_objects::Location& from_here, | |
131 const base::Closure& task); | |
132 | |
133 // Implements the worker pool shutdown. This should be called during app | |
134 // shutdown, and will discard/join with appropriate tasks before returning. | |
135 // After this call, subsequent calls to post tasks will fail. | |
136 void Shutdown(); | |
137 | |
138 // Called by tests to set the testing observer. This is NULL by default | |
139 // and ownership of the pointer is kept with the caller. | |
140 void SetTestingObserver(TestingObserver* observer); | |
141 | |
142 private: | |
143 class Inner; | |
144 scoped_refptr<Inner> inner_; | |
145 | |
146 DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool); | |
147 }; | |
148 | |
149 #endif // CONTENT_COMMON_SEQUENCED_WORKER_POOL_H_ | |
OLD | NEW |