| Index: base/task/task_queue_manager.h
|
| diff --git a/base/task/task_queue_manager.h b/base/task/task_queue_manager.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b61c3cb757acb79054bb7ae4f26c0930bda0f701
|
| --- /dev/null
|
| +++ b/base/task/task_queue_manager.h
|
| @@ -0,0 +1,153 @@
|
| +// Copyright 2014 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_TASK_TASK_QUEUE_MANAGER_H_
|
| +#define BASE_TASK_TASK_QUEUE_MANAGER_H_
|
| +
|
| +#include "base/atomic_sequence_num.h"
|
| +#include "base/debug/task_annotator.h"
|
| +#include "base/macros.h"
|
| +#include "base/memory/scoped_vector.h"
|
| +#include "base/memory/weak_ptr.h"
|
| +#include "base/pending_task.h"
|
| +#include "base/single_thread_task_runner.h"
|
| +#include "base/synchronization/lock.h"
|
| +#include "base/threading/thread_checker.h"
|
| +
|
| +namespace base {
|
| +class TaskQueueSelector;
|
| +
|
| +// The task queue manager provides N task queues and a selector interface for
|
| +// choosing which task queue to service next. Each task queue consists of two
|
| +// sub queues:
|
| +//
|
| +// 1. Incoming task queue. Tasks that are posted get immediately appended here.
|
| +// When a task is appended into an empty incoming queue, the task manager
|
| +// work function (DoWork) is scheduled to run on the main task runner.
|
| +//
|
| +// 2. Work queue. If a work queue is empty when DoWork() is entered, tasks from
|
| +// the incoming task queue (if any) are moved here. The work queues are
|
| +// registered with the selector as input to the scheduling decision.
|
| +//
|
| +class BASE_EXPORT TaskQueueManager {
|
| + public:
|
| + // Create a task queue manager with |task_queue_count| task queues.
|
| + // |main_task_runner| identifies the thread on which where the tasks are
|
| + // eventually run. |selector| is used to choose which task queue to service.
|
| + // It should outlive this class.
|
| + TaskQueueManager(size_t task_queue_count,
|
| + scoped_refptr<SingleThreadTaskRunner> main_task_runner,
|
| + TaskQueueSelector* selector);
|
| + ~TaskQueueManager();
|
| +
|
| + // Returns the task runner which targets the queue selected by |queue_index|.
|
| + scoped_refptr<SingleThreadTaskRunner> TaskRunnerForQueue(size_t queue_index);
|
| +
|
| + // If |auto_pump| is false, tasks posted to the given incoming queue will not
|
| + // be automatically scheduled for execution or transferred to the work queue.
|
| + // Instead, the selector should call PumpQueue() when necessary to bring in
|
| + // new tasks for execution.
|
| + void SetAutoPump(size_t queue_index, bool auto_pump);
|
| +
|
| + // Reloads new tasks from the incoming queue for |queue_index|. After this,
|
| + // this function ensures that the tasks in the work queue, if any, are
|
| + // scheduled for execution.
|
| + //
|
| + // This function only needs to be called if automatic pumping is disabled
|
| + // for |queue_index|. See |SetQueueAutoPump|. By default automatic pumping is
|
| + // enabled for all queues.
|
| + void PumpQueue(size_t queue_index);
|
| +
|
| + // Returns true if there are any tasks in either the work or incoming task
|
| + // queue identified by |queue_index|. Note that this function involves taking
|
| + // a lock, so calling it has some overhead.
|
| + bool PollQueue(size_t queue_index);
|
| +
|
| + private:
|
| + class TaskRunner : public SingleThreadTaskRunner {
|
| + public:
|
| + TaskRunner(TaskQueueManager* task_queue_manager, size_t queue_index);
|
| +
|
| + // SingleThreadTaskRunner implementation.
|
| + virtual bool RunsTasksOnCurrentThread() const override;
|
| + virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
|
| + const Closure& task,
|
| + TimeDelta delay) override;
|
| + virtual bool PostNonNestableDelayedTask(
|
| + const tracked_objects::Location& from_here,
|
| + const Closure& task,
|
| + TimeDelta delay) override;
|
| +
|
| + private:
|
| + virtual ~TaskRunner();
|
| +
|
| + TaskQueueManager* task_queue_manager_;
|
| + const size_t queue_index_;
|
| + };
|
| + friend class TaskRunner;
|
| +
|
| + // Adds a task at the end of the incoming task queue for |queue_index| and
|
| + // schedules a call to DoWork() if the incoming queue was empty and automatic
|
| + // pumping is enabled. Can be called on an arbitrary thread.
|
| + void EnqueueTask(size_t queue_index, const PendingTask& pending_task);
|
| +
|
| + // Post a task to call DoWork() on the main task runner.
|
| + void ScheduleWork();
|
| +
|
| + // Use the selector to choose a pending task and run it.
|
| + void DoWork();
|
| +
|
| + // Reloads the work queue identified by |queue_index| and returns true if
|
| + // it ended up having tasks. The work queue must be empty when this function
|
| + // is called.
|
| + bool ReloadWorkQueue(size_t queue_index);
|
| +
|
| + // Returns true if any work queue is non-empty.
|
| + bool ReloadWorkQueues();
|
| +
|
| + // Runs a single task from the work queue designated by |queue_index|. The
|
| + // queue must not be empty.
|
| + void RunTaskFromWorkQueue(size_t queue_index);
|
| +
|
| + bool RunsTasksOnCurrentThread() const;
|
| + bool PostDelayedTask(size_t queue_index,
|
| + const tracked_objects::Location& from_here,
|
| + const Closure& task,
|
| + TimeDelta delay);
|
| + bool PostNonNestableDelayedTask(size_t queue_index,
|
| + const tracked_objects::Location& from_here,
|
| + const Closure& task,
|
| + TimeDelta delay);
|
| + struct InternalTaskQueue {
|
| + InternalTaskQueue();
|
| + ~InternalTaskQueue();
|
| +
|
| + scoped_refptr<TaskRunner> task_runner;
|
| +
|
| + Lock incoming_queue_lock;
|
| + TaskQueue incoming_queue;
|
| +
|
| + bool auto_pump;
|
| + TaskQueue work_queue;
|
| + };
|
| +
|
| + InternalTaskQueue* Queue(size_t queue_index) const;
|
| + void PumpQueueLocked(InternalTaskQueue* queue);
|
| +
|
| + ScopedVector<InternalTaskQueue> queues_;
|
| + AtomicSequenceNumber task_sequence_num_;
|
| + debug::TaskAnnotator task_annotator_;
|
| +
|
| + base::ThreadChecker main_thread_checker_;
|
| + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
|
| + TaskQueueSelector* selector_;
|
| +
|
| + base::WeakPtrFactory<TaskQueueManager> weak_factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TaskQueueManager);
|
| +};
|
| +
|
| +} // namespace content
|
| +
|
| +#endif // BASE_TASK_TASK_QUEUE_MANAGER_H_
|
|
|