Chromium Code Reviews| 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 |