security/sandbox/chromium/base/threading/sequenced_worker_pool.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/sandbox/chromium/base/threading/sequenced_worker_pool.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,358 @@
     1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#ifndef BASE_THREADING_SEQUENCED_WORKER_POOL_H_
     1.9 +#define BASE_THREADING_SEQUENCED_WORKER_POOL_H_
    1.10 +
    1.11 +#include <cstddef>
    1.12 +#include <string>
    1.13 +
    1.14 +#include "base/base_export.h"
    1.15 +#include "base/basictypes.h"
    1.16 +#include "base/callback_forward.h"
    1.17 +#include "base/memory/ref_counted.h"
    1.18 +#include "base/memory/scoped_ptr.h"
    1.19 +#include "base/task_runner.h"
    1.20 +
    1.21 +namespace tracked_objects {
    1.22 +class Location;
    1.23 +}  // namespace tracked_objects
    1.24 +
    1.25 +namespace base {
    1.26 +
    1.27 +class MessageLoopProxy;
    1.28 +
    1.29 +template <class T> class DeleteHelper;
    1.30 +
    1.31 +class SequencedTaskRunner;
    1.32 +
    1.33 +// A worker thread pool that enforces ordering between sets of tasks. It also
    1.34 +// allows you to specify what should happen to your tasks on shutdown.
    1.35 +//
    1.36 +// To enforce ordering, get a unique sequence token from the pool and post all
    1.37 +// tasks you want to order with the token. All tasks with the same token are
    1.38 +// guaranteed to execute serially, though not necessarily on the same thread.
    1.39 +// This means that:
    1.40 +//
    1.41 +//   - No two tasks with the same token will run at the same time.
    1.42 +//
    1.43 +//   - Given two tasks T1 and T2 with the same token such that T2 will
    1.44 +//     run after T1, then T2 will start after T1 is destroyed.
    1.45 +//
    1.46 +//   - If T2 will run after T1, then all memory changes in T1 and T1's
    1.47 +//     destruction will be visible to T2.
    1.48 +//
    1.49 +// Example:
    1.50 +//   SequencedWorkerPool::SequenceToken token = pool.GetSequenceToken();
    1.51 +//   pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN,
    1.52 +//                                FROM_HERE, base::Bind(...));
    1.53 +//   pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN,
    1.54 +//                                FROM_HERE, base::Bind(...));
    1.55 +//
    1.56 +// You can make named sequence tokens to make it easier to share a token
    1.57 +// across different components.
    1.58 +//
    1.59 +// You can also post tasks to the pool without ordering using PostWorkerTask.
    1.60 +// These will be executed in an unspecified order. The order of execution
    1.61 +// between tasks with different sequence tokens is also unspecified.
    1.62 +//
    1.63 +// This class may be leaked on shutdown to facilitate fast shutdown. The
    1.64 +// expected usage, however, is to call Shutdown(), which correctly accounts
    1.65 +// for CONTINUE_ON_SHUTDOWN behavior and is required for BLOCK_SHUTDOWN
    1.66 +// behavior.
    1.67 +//
    1.68 +// Implementation note: This does not use a base::WorkerPool since that does
    1.69 +// not enforce shutdown semantics or allow us to specify how many worker
    1.70 +// threads to run. For the typical use case of random background work, we don't
    1.71 +// necessarily want to be super aggressive about creating threads.
    1.72 +//
    1.73 +// Note that SequencedWorkerPool is RefCountedThreadSafe (inherited
    1.74 +// from TaskRunner).
    1.75 +class BASE_EXPORT SequencedWorkerPool : public TaskRunner {
    1.76 + public:
    1.77 +  // Defines what should happen to a task posted to the worker pool on
    1.78 +  // shutdown.
    1.79 +  enum WorkerShutdown {
    1.80 +    // Tasks posted with this mode which have not run at shutdown will be
    1.81 +    // deleted rather than run, and any tasks with this mode running at
    1.82 +    // shutdown will be ignored (the worker thread will not be joined).
    1.83 +    //
    1.84 +    // This option provides a nice way to post stuff you don't want blocking
    1.85 +    // shutdown. For example, you might be doing a slow DNS lookup and if it's
    1.86 +    // blocked on the OS, you may not want to stop shutdown, since the result
    1.87 +    // doesn't really matter at that point.
    1.88 +    //
    1.89 +    // However, you need to be very careful what you do in your callback when
    1.90 +    // you use this option. Since the thread will continue to run until the OS
    1.91 +    // terminates the process, the app can be in the process of tearing down
    1.92 +    // when you're running. This means any singletons or global objects you
    1.93 +    // use may suddenly become invalid out from under you. For this reason,
    1.94 +    // it's best to use this only for slow but simple operations like the DNS
    1.95 +    // example.
    1.96 +    CONTINUE_ON_SHUTDOWN,
    1.97 +
    1.98 +    // Tasks posted with this mode that have not started executing at
    1.99 +    // shutdown will be deleted rather than executed. However, any tasks that
   1.100 +    // have already begun executing when shutdown is called will be allowed
   1.101 +    // to continue, and will block shutdown until completion.
   1.102 +    //
   1.103 +    // Note: Because Shutdown() may block while these tasks are executing,
   1.104 +    // care must be taken to ensure that they do not block on the thread that
   1.105 +    // called Shutdown(), as this may lead to deadlock.
   1.106 +    SKIP_ON_SHUTDOWN,
   1.107 +
   1.108 +    // Tasks posted with this mode will block shutdown until they're
   1.109 +    // executed. Since this can have significant performance implications,
   1.110 +    // use sparingly.
   1.111 +    //
   1.112 +    // Generally, this should be used only for user data, for example, a task
   1.113 +    // writing a preference file.
   1.114 +    //
   1.115 +    // If a task is posted during shutdown, it will not get run since the
   1.116 +    // workers may already be stopped. In this case, the post operation will
   1.117 +    // fail (return false) and the task will be deleted.
   1.118 +    BLOCK_SHUTDOWN,
   1.119 +  };
   1.120 +
   1.121 +  // Opaque identifier that defines sequencing of tasks posted to the worker
   1.122 +  // pool.
   1.123 +  class SequenceToken {
   1.124 +   public:
   1.125 +    SequenceToken() : id_(0) {}
   1.126 +    ~SequenceToken() {}
   1.127 +
   1.128 +    bool Equals(const SequenceToken& other) const {
   1.129 +      return id_ == other.id_;
   1.130 +    }
   1.131 +
   1.132 +    // Returns false if current thread is executing an unsequenced task.
   1.133 +    bool IsValid() const {
   1.134 +      return id_ != 0;
   1.135 +    }
   1.136 +
   1.137 +   private:
   1.138 +    friend class SequencedWorkerPool;
   1.139 +
   1.140 +    explicit SequenceToken(int id) : id_(id) {}
   1.141 +
   1.142 +    int id_;
   1.143 +  };
   1.144 +
   1.145 +  // Allows tests to perform certain actions.
   1.146 +  class TestingObserver {
   1.147 +   public:
   1.148 +    virtual ~TestingObserver() {}
   1.149 +    virtual void OnHasWork() = 0;
   1.150 +    virtual void WillWaitForShutdown() = 0;
   1.151 +    virtual void OnDestruct() = 0;
   1.152 +  };
   1.153 +
   1.154 +  // Gets the SequencedToken of the current thread.
   1.155 +  // If current thread is not a SequencedWorkerPool worker thread or is running
   1.156 +  // an unsequenced task, returns an invalid SequenceToken.
   1.157 +  static SequenceToken GetSequenceTokenForCurrentThread();
   1.158 +
   1.159 +  // When constructing a SequencedWorkerPool, there must be a
   1.160 +  // MessageLoop on the current thread unless you plan to deliberately
   1.161 +  // leak it.
   1.162 +
   1.163 +  // Pass the maximum number of threads (they will be lazily created as needed)
   1.164 +  // and a prefix for the thread name to aid in debugging.
   1.165 +  SequencedWorkerPool(size_t max_threads,
   1.166 +                      const std::string& thread_name_prefix);
   1.167 +
   1.168 +  // Like above, but with |observer| for testing.  Does not take
   1.169 +  // ownership of |observer|.
   1.170 +  SequencedWorkerPool(size_t max_threads,
   1.171 +                      const std::string& thread_name_prefix,
   1.172 +                      TestingObserver* observer);
   1.173 +
   1.174 +  // Returns a unique token that can be used to sequence tasks posted to
   1.175 +  // PostSequencedWorkerTask(). Valid tokens are always nonzero.
   1.176 +  SequenceToken GetSequenceToken();
   1.177 +
   1.178 +  // Returns the sequence token associated with the given name. Calling this
   1.179 +  // function multiple times with the same string will always produce the
   1.180 +  // same sequence token. If the name has not been used before, a new token
   1.181 +  // will be created.
   1.182 +  SequenceToken GetNamedSequenceToken(const std::string& name);
   1.183 +
   1.184 +  // Returns a SequencedTaskRunner wrapper which posts to this
   1.185 +  // SequencedWorkerPool using the given sequence token. Tasks with nonzero
   1.186 +  // delay are posted with SKIP_ON_SHUTDOWN behavior and tasks with zero delay
   1.187 +  // are posted with BLOCK_SHUTDOWN behavior.
   1.188 +  scoped_refptr<SequencedTaskRunner> GetSequencedTaskRunner(
   1.189 +      SequenceToken token);
   1.190 +
   1.191 +  // Returns a SequencedTaskRunner wrapper which posts to this
   1.192 +  // SequencedWorkerPool using the given sequence token. Tasks with nonzero
   1.193 +  // delay are posted with SKIP_ON_SHUTDOWN behavior and tasks with zero delay
   1.194 +  // are posted with the given shutdown behavior.
   1.195 +  scoped_refptr<SequencedTaskRunner> GetSequencedTaskRunnerWithShutdownBehavior(
   1.196 +      SequenceToken token,
   1.197 +      WorkerShutdown shutdown_behavior);
   1.198 +
   1.199 +  // Returns a TaskRunner wrapper which posts to this SequencedWorkerPool using
   1.200 +  // the given shutdown behavior. Tasks with nonzero delay are posted with
   1.201 +  // SKIP_ON_SHUTDOWN behavior and tasks with zero delay are posted with the
   1.202 +  // given shutdown behavior.
   1.203 +  scoped_refptr<TaskRunner> GetTaskRunnerWithShutdownBehavior(
   1.204 +      WorkerShutdown shutdown_behavior);
   1.205 +
   1.206 +  // Posts the given task for execution in the worker pool. Tasks posted with
   1.207 +  // this function will execute in an unspecified order on a background thread.
   1.208 +  // Returns true if the task was posted. If your tasks have ordering
   1.209 +  // requirements, see PostSequencedWorkerTask().
   1.210 +  //
   1.211 +  // This class will attempt to delete tasks that aren't run
   1.212 +  // (non-block-shutdown semantics) but can't guarantee that this happens. If
   1.213 +  // all worker threads are busy running CONTINUE_ON_SHUTDOWN tasks, there
   1.214 +  // will be no workers available to delete these tasks. And there may be
   1.215 +  // tasks with the same sequence token behind those CONTINUE_ON_SHUTDOWN
   1.216 +  // tasks. Deleting those tasks before the previous one has completed could
   1.217 +  // cause nondeterministic crashes because the task could be keeping some
   1.218 +  // objects alive which do work in their destructor, which could voilate the
   1.219 +  // assumptions of the running task.
   1.220 +  //
   1.221 +  // The task will be guaranteed to run to completion before shutdown
   1.222 +  // (BLOCK_SHUTDOWN semantics).
   1.223 +  //
   1.224 +  // Returns true if the task was posted successfully. This may fail during
   1.225 +  // shutdown regardless of the specified ShutdownBehavior.
   1.226 +  bool PostWorkerTask(const tracked_objects::Location& from_here,
   1.227 +                      const Closure& task);
   1.228 +
   1.229 +  // Same as PostWorkerTask but allows a delay to be specified (although doing
   1.230 +  // so changes the shutdown behavior). The task will be run after the given
   1.231 +  // delay has elapsed.
   1.232 +  //
   1.233 +  // If the delay is nonzero, the task won't be guaranteed to run to completion
   1.234 +  // before shutdown (SKIP_ON_SHUTDOWN semantics) to avoid shutdown hangs.
   1.235 +  // If the delay is zero, this behaves exactly like PostWorkerTask, i.e. the
   1.236 +  // task will be guaranteed to run to completion before shutdown
   1.237 +  // (BLOCK_SHUTDOWN semantics).
   1.238 +  bool PostDelayedWorkerTask(const tracked_objects::Location& from_here,
   1.239 +                             const Closure& task,
   1.240 +                             TimeDelta delay);
   1.241 +
   1.242 +  // Same as PostWorkerTask but allows specification of the shutdown behavior.
   1.243 +  bool PostWorkerTaskWithShutdownBehavior(
   1.244 +      const tracked_objects::Location& from_here,
   1.245 +      const Closure& task,
   1.246 +      WorkerShutdown shutdown_behavior);
   1.247 +
   1.248 +  // Like PostWorkerTask above, but provides sequencing semantics. This means
   1.249 +  // that tasks posted with the same sequence token (see GetSequenceToken())
   1.250 +  // are guaranteed to execute in order. This is useful in cases where you're
   1.251 +  // doing operations that may depend on previous ones, like appending to a
   1.252 +  // file.
   1.253 +  //
   1.254 +  // The task will be guaranteed to run to completion before shutdown
   1.255 +  // (BLOCK_SHUTDOWN semantics).
   1.256 +  //
   1.257 +  // Returns true if the task was posted successfully. This may fail during
   1.258 +  // shutdown regardless of the specified ShutdownBehavior.
   1.259 +  bool PostSequencedWorkerTask(SequenceToken sequence_token,
   1.260 +                               const tracked_objects::Location& from_here,
   1.261 +                               const Closure& task);
   1.262 +
   1.263 +  // Like PostSequencedWorkerTask above, but allows you to specify a named
   1.264 +  // token, which saves an extra call to GetNamedSequenceToken.
   1.265 +  bool PostNamedSequencedWorkerTask(const std::string& token_name,
   1.266 +                                    const tracked_objects::Location& from_here,
   1.267 +                                    const Closure& task);
   1.268 +
   1.269 +  // Same as PostSequencedWorkerTask but allows a delay to be specified
   1.270 +  // (although doing so changes the shutdown behavior). The task will be run
   1.271 +  // after the given delay has elapsed.
   1.272 +  //
   1.273 +  // If the delay is nonzero, the task won't be guaranteed to run to completion
   1.274 +  // before shutdown (SKIP_ON_SHUTDOWN semantics) to avoid shutdown hangs.
   1.275 +  // If the delay is zero, this behaves exactly like PostSequencedWorkerTask,
   1.276 +  // i.e. the task will be guaranteed to run to completion before shutdown
   1.277 +  // (BLOCK_SHUTDOWN semantics).
   1.278 +  bool PostDelayedSequencedWorkerTask(
   1.279 +      SequenceToken sequence_token,
   1.280 +      const tracked_objects::Location& from_here,
   1.281 +      const Closure& task,
   1.282 +      TimeDelta delay);
   1.283 +
   1.284 +  // Same as PostSequencedWorkerTask but allows specification of the shutdown
   1.285 +  // behavior.
   1.286 +  bool PostSequencedWorkerTaskWithShutdownBehavior(
   1.287 +      SequenceToken sequence_token,
   1.288 +      const tracked_objects::Location& from_here,
   1.289 +      const Closure& task,
   1.290 +      WorkerShutdown shutdown_behavior);
   1.291 +
   1.292 +  // TaskRunner implementation. Forwards to PostDelayedWorkerTask().
   1.293 +  virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
   1.294 +                               const Closure& task,
   1.295 +                               TimeDelta delay) OVERRIDE;
   1.296 +  virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
   1.297 +
   1.298 +  // Returns true if the current thread is processing a task with the given
   1.299 +  // sequence_token.
   1.300 +  bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const;
   1.301 +
   1.302 +  // Blocks until all pending tasks are complete. This should only be called in
   1.303 +  // unit tests when you want to validate something that should have happened.
   1.304 +  // This will not flush delayed tasks; delayed tasks get deleted.
   1.305 +  //
   1.306 +  // Note that calling this will not prevent other threads from posting work to
   1.307 +  // the queue while the calling thread is waiting on Flush(). In this case,
   1.308 +  // Flush will return only when there's no more work in the queue. Normally,
   1.309 +  // this doesn't come up since in a test, all the work is being posted from
   1.310 +  // the main thread.
   1.311 +  void FlushForTesting();
   1.312 +
   1.313 +  // Spuriously signal that there is work to be done.
   1.314 +  void SignalHasWorkForTesting();
   1.315 +
   1.316 +  // Implements the worker pool shutdown. This should be called during app
   1.317 +  // shutdown, and will discard/join with appropriate tasks before returning.
   1.318 +  // After this call, subsequent calls to post tasks will fail.
   1.319 +  //
   1.320 +  // Must be called from the same thread this object was constructed on.
   1.321 +  void Shutdown() { Shutdown(0); }
   1.322 +
   1.323 +  // A variant that allows an arbitrary number of new blocking tasks to
   1.324 +  // be posted during shutdown from within tasks that execute during shutdown.
   1.325 +  // Only tasks designated as BLOCKING_SHUTDOWN will be allowed, and only if
   1.326 +  // posted by tasks that are not designated as CONTINUE_ON_SHUTDOWN. Once
   1.327 +  // the limit is reached, subsequent calls to post task fail in all cases.
   1.328 +  //
   1.329 +  // Must be called from the same thread this object was constructed on.
   1.330 +  void Shutdown(int max_new_blocking_tasks_after_shutdown);
   1.331 +
   1.332 +  // Check if Shutdown was called for given threading pool. This method is used
   1.333 +  // for aborting time consuming operation to avoid blocking shutdown.
   1.334 +  //
   1.335 +  // Can be called from any thread.
   1.336 +  bool IsShutdownInProgress();
   1.337 +
   1.338 + protected:
   1.339 +  virtual ~SequencedWorkerPool();
   1.340 +
   1.341 +  virtual void OnDestruct() const OVERRIDE;
   1.342 +
   1.343 + private:
   1.344 +  friend class RefCountedThreadSafe<SequencedWorkerPool>;
   1.345 +  friend class DeleteHelper<SequencedWorkerPool>;
   1.346 +
   1.347 +  class Inner;
   1.348 +  class Worker;
   1.349 +
   1.350 +  const scoped_refptr<MessageLoopProxy> constructor_message_loop_;
   1.351 +
   1.352 +  // Avoid pulling in too many headers by putting (almost) everything
   1.353 +  // into |inner_|.
   1.354 +  const scoped_ptr<Inner> inner_;
   1.355 +
   1.356 +  DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool);
   1.357 +};
   1.358 +
   1.359 +}  // namespace base
   1.360 +
   1.361 +#endif  // BASE_THREADING_SEQUENCED_WORKER_POOL_H_

mercurial