| Index: base/threading/sequenced_worker_pool.h
|
| ===================================================================
|
| --- base/threading/sequenced_worker_pool.h (revision 0)
|
| +++ base/threading/sequenced_worker_pool.h (revision 0)
|
| @@ -0,0 +1,206 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef BASE_THREADING_SEQUENCED_WORKER_POOL_H_
|
| +#define BASE_THREADING_SEQUENCED_WORKER_POOL_H_
|
| +#pragma once
|
| +
|
| +#include <string>
|
| +
|
| +#include "base/callback.h"
|
| +#include "base/memory/linked_ptr.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/tracked_objects.h"
|
| +#include "base/base_export.h"
|
| +
|
| +namespace base {
|
| +
|
| +// A worker thread pool that enforces ordering between sets of tasks. It also
|
| +// allows you to specify what should happen to your tasks on shutdown.
|
| +//
|
| +// To enforce ordering, get a unique sequence token from the pool and post all
|
| +// tasks you want to order with the token. All tasks with the same token are
|
| +// guaranteed to execute serially, though not necessarily on the same thread.
|
| +//
|
| +// Example:
|
| +// SequencedWorkerPool::SequenceToken token = pool.GetSequenceToken();
|
| +// pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN,
|
| +// FROM_HERE, base::Bind(...));
|
| +// pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN,
|
| +// FROM_HERE, base::Bind(...));
|
| +//
|
| +// You can make named sequence tokens to make it easier to share a token
|
| +// across different components.
|
| +//
|
| +// You can also post tasks to the pool without ordering using PostWorkerTask.
|
| +// These will be executed in an unspecified order. The order of execution
|
| +// between tasks with different sequence tokens is also unspecified.
|
| +//
|
| +// This class is designed to be leaked on shutdown to allow the
|
| +// CONTINUE_ON_SHUTDOWN behavior to be implemented. To enforce the
|
| +// BLOCK_SHUTDOWN behavior, you must call Shutdown() which will wait until
|
| +// the necessary tasks have completed.
|
| +//
|
| +// Implementation note: This does not use a base::WorkerPool since that does
|
| +// not enforce shutdown semantics or allow us to specify how many worker
|
| +// threads to run. For the typical use case of random background work, we don't
|
| +// necessarily want to be super aggressive about creating threads.
|
| +class BASE_EXPORT SequencedWorkerPool {
|
| + public:
|
| + // Defines what should happen to a task posted to the worker pool on shutdown.
|
| + enum WorkerShutdown {
|
| + // Tasks posted with this mode which have not run at shutdown will be
|
| + // deleted rather than run, and any tasks with this mode running at
|
| + // shutdown will be ignored (the worker thread will not be joined).
|
| + //
|
| + // This option provides a nice way to post stuff you don't want blocking
|
| + // shutdown. For example, you might be doing a slow DNS lookup and if it's
|
| + // blocked on the OS, you may not want to stop shutdown, since the result
|
| + // doesn't really matter at that point.
|
| + //
|
| + // However, you need to be very careful what you do in your callback when
|
| + // you use this option. Since the thread will continue to run until the OS
|
| + // terminates the process, the app can be in the process of tearing down
|
| + // when you're running. This means any singletons or global objects you
|
| + // use may suddenly become invalid out from under you. For this reason,
|
| + // it's best to use this only for slow but simple operations like the DNS
|
| + // example.
|
| + CONTINUE_ON_SHUTDOWN,
|
| +
|
| + // Tasks posted with this mode that have not started executing at shutdown
|
| + // will be deleted rather than executed. However, tasks already in progress
|
| + // will be completed.
|
| + SKIP_ON_SHUTDOWN,
|
| +
|
| + // Tasks posted with this mode will block browser shutdown until they're
|
| + // executed. Since this can have significant performance implications, use
|
| + // sparingly.
|
| + //
|
| + // Generally, this should be used only for user data, for example, a task
|
| + // writing a preference file.
|
| + //
|
| + // If a task is posted during shutdown, it will not get run since the
|
| + // workers may already be stopped. In this case, the post operation will
|
| + // fail (return false) and the task will be deleted.
|
| + BLOCK_SHUTDOWN,
|
| + };
|
| +
|
| + // Opaque identifier that defines sequencing of tasks posted to the worker
|
| + // pool. See NewSequenceToken().
|
| + class SequenceToken {
|
| + public:
|
| + explicit SequenceToken() : id_(0) {}
|
| + ~SequenceToken() {}
|
| +
|
| + bool Equals(const SequenceToken& other) const {
|
| + return id_ == other.id_;
|
| + }
|
| +
|
| + private:
|
| + friend class SequencedWorkerPool;
|
| +
|
| + SequenceToken(int id) : id_(id) {}
|
| +
|
| + int id_;
|
| + };
|
| +
|
| + // Allows tests to perform certain actions.
|
| + class TestingObserver {
|
| + public:
|
| + virtual ~TestingObserver() {}
|
| + virtual void WillWaitForShutdown() = 0;
|
| + };
|
| +
|
| + // Pass the maximum number of threads (they will be lazily created as needed)
|
| + // and a prefix for the thread name to ad in debugging.
|
| + SequencedWorkerPool(size_t max_threads,
|
| + const std::string& thread_name_prefix);
|
| + ~SequencedWorkerPool();
|
| +
|
| + // Returns a unique token that can be used to sequence tasks posted to
|
| + // PostSequencedWorkerTask(). Valid tokens are alwys nonzero.
|
| + SequenceToken GetSequenceToken();
|
| +
|
| + // Returns the sequence token associated with the given name. Calling this
|
| + // function multiple times with the same string will always produce the
|
| + // same sequence token. If the name has not been used before, a new token
|
| + // will be created.
|
| + SequenceToken GetNamedSequenceToken(const std::string& name);
|
| +
|
| + // Posts the given task for execution in the worker pool. Tasks posted with
|
| + // this function will execute in an unspecified order on a background thread.
|
| + // Returns true if the task was posted. If your tasks have ordering
|
| + // requirements, see PostSequencedWorkerTask().
|
| + //
|
| + // This class will attempt to delete tasks that aren't run
|
| + // (non-block-shutdown semantics) but can't guarantee that this happens. If
|
| + // all worker threads are busy running CONTINUE_ON_SHUTDOWN tasks, there
|
| + // will be no workers available to delete these tasks. And there may be
|
| + // tasks with the same sequence token behind those CONTINUE_ON_SHUTDOWN
|
| + // tasks. Deleting those tasks before the previous one has completed could
|
| + // cause nondeterministic crashes because the task could be keeping some
|
| + // objects alive which do work in their destructor, which could voilate the
|
| + // assumptions of the running task.
|
| + //
|
| + // The task will be guaranteed to run to completion before shutdown
|
| + // (BLOCK_SHUTDOWN semantics).
|
| + //
|
| + // Returns true if the task was posted successfully. This may fail during
|
| + // shutdown regardless of the specified ShutdownBehavior.
|
| + bool PostWorkerTask(const tracked_objects::Location& from_here,
|
| + const base::Closure& task);
|
| +
|
| + // Same as PostWorkerTask but allows specification of the shutdown behavior.
|
| + bool PostWorkerTaskWithShutdownBehavior(
|
| + const tracked_objects::Location& from_here,
|
| + const base::Closure& task,
|
| + WorkerShutdown shutdown_behavior);
|
| +
|
| + // Like PostWorkerTask above, but provides sequencing semantics. This means
|
| + // that tasks posted with the same sequence token (see GetSequenceToken())
|
| + // are guaranteed to execute in order. This is useful in cases where you're
|
| + // doing operations that may depend on previous ones, like appending to a
|
| + // file.
|
| + //
|
| + // The task will be guaranteed to run to completion before shutdown
|
| + // (BLOCK_SHUTDOWN semantics).
|
| + //
|
| + // Returns true if the task was posted successfully. This may fail during
|
| + // shutdown regardless of the specified ShutdownBehavior.
|
| + bool PostSequencedWorkerTask(SequenceToken sequence_token,
|
| + const tracked_objects::Location& from_here,
|
| + const base::Closure& task);
|
| +
|
| + // Same as PostSequencedWorkerTask but allows specification of the shutdown
|
| + // behavior.
|
| + bool PostSequencedWorkerTaskWithShutdownBehavior(
|
| + SequenceToken sequence_token,
|
| + const tracked_objects::Location& from_here,
|
| + const base::Closure& task,
|
| + WorkerShutdown shutdown_behavior);
|
| +
|
| + // Implements the worker pool shutdown. This should be called during app
|
| + // shutdown, and will discard/join with appropriate tasks before returning.
|
| + // After this call, subsequent calls to post tasks will fail.
|
| + void Shutdown();
|
| +
|
| + // Called by tests to set the testing observer. This is NULL by default
|
| + // and ownership of the pointer is kept with the caller.
|
| + void SetTestingObserver(TestingObserver* observer);
|
| +
|
| + private:
|
| + class Inner;
|
| + class Worker;
|
| +
|
| + friend class Inner;
|
| + friend class Worker;
|
| +
|
| + scoped_refptr<Inner> inner_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool);
|
| +};
|
| +
|
| +} // namespace base
|
| +
|
| +#endif // BASE_THREADING_SEQUENCED_WORKER_POOL_H_
|
|
|