1// Copyright 2013 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 CC_RESOURCES_WORKER_POOL_H_
6#define CC_RESOURCES_WORKER_POOL_H_
7
8#include <deque>
9#include <string>
10#include <vector>
11
12#include "base/cancelable_callback.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/weak_ptr.h"
16#include "base/message_loop/message_loop.h"
17#include "cc/base/cc_export.h"
18#include "cc/base/scoped_ptr_hash_map.h"
19
20namespace cc {
21namespace internal {
22
23class CC_EXPORT WorkerPoolTask
24    : public base::RefCountedThreadSafe<WorkerPoolTask> {
25 public:
26  virtual void RunOnWorkerThread(unsigned thread_index) = 0;
27  virtual void CompleteOnOriginThread() = 0;
28
29  void DidSchedule();
30  void WillRun();
31  void DidRun();
32  void WillComplete();
33  void DidComplete();
34
35  bool HasFinishedRunning() const;
36  bool HasCompleted() const;
37
38 protected:
39  friend class base::RefCountedThreadSafe<WorkerPoolTask>;
40
41  WorkerPoolTask();
42  virtual ~WorkerPoolTask();
43
44 private:
45  bool did_schedule_;
46  bool did_run_;
47  bool did_complete_;
48};
49
50class CC_EXPORT GraphNode {
51 public:
52  typedef std::vector<GraphNode*> Vector;
53
54  GraphNode(internal::WorkerPoolTask* task, unsigned priority);
55  ~GraphNode();
56
57  WorkerPoolTask* task() { return task_; }
58
59  void add_dependent(GraphNode* dependent) {
60    DCHECK(dependent);
61    dependents_.push_back(dependent);
62  }
63  const Vector& dependents() const { return dependents_; }
64
65  unsigned priority() const { return priority_; }
66
67  unsigned num_dependencies() const { return num_dependencies_; }
68  void add_dependency() { ++num_dependencies_; }
69  void remove_dependency() {
70    DCHECK(num_dependencies_);
71    --num_dependencies_;
72  }
73
74 private:
75  WorkerPoolTask* task_;
76  Vector dependents_;
77  unsigned priority_;
78  unsigned num_dependencies_;
79
80  DISALLOW_COPY_AND_ASSIGN(GraphNode);
81};
82
83}  // namespace internal
84}  // namespace cc
85
86#if defined(COMPILER_GCC)
87namespace BASE_HASH_NAMESPACE {
88template <> struct hash<cc::internal::WorkerPoolTask*> {
89  size_t operator()(cc::internal::WorkerPoolTask* ptr) const {
90    return hash<size_t>()(reinterpret_cast<size_t>(ptr));
91  }
92};
93}  // namespace BASE_HASH_NAMESPACE
94#endif  // COMPILER
95
96namespace cc {
97
98// A worker thread pool that runs tasks provided by task graph and
99// guarantees completion of all pending tasks at shutdown.
100class CC_EXPORT WorkerPool {
101 public:
102  virtual ~WorkerPool();
103
104  // Tells the worker pool to shutdown and returns once all pending tasks have
105  // completed.
106  virtual void Shutdown();
107
108  // Force a check for completed tasks.
109  virtual void CheckForCompletedTasks();
110
111 protected:
112  // A task graph contains a unique set of tasks with edges between
113  // dependencies pointing in the direction of the dependents. Each task
114  // need to be assigned a unique priority and a run count that matches
115  // the number of dependencies.
116  typedef ScopedPtrHashMap<internal::WorkerPoolTask*, internal::GraphNode>
117      GraphNodeMap;
118  typedef GraphNodeMap TaskGraph;
119
120  WorkerPool(size_t num_threads, const std::string& thread_name_prefix);
121
122  // Schedule running of tasks in |graph|. Any previously scheduled tasks
123  // that are not already running will be canceled. Canceled tasks don't run
124  // but completion of them is still processed.
125  void SetTaskGraph(TaskGraph* graph);
126
127 private:
128  class Inner;
129  friend class Inner;
130
131  typedef std::vector<scoped_refptr<internal::WorkerPoolTask> > TaskVector;
132
133  void ProcessCompletedTasks(const TaskVector& completed_tasks);
134
135  bool in_dispatch_completion_callbacks_;
136
137  // Hide the gory details of the worker pool in |inner_|.
138  const scoped_ptr<Inner> inner_;
139};
140
141}  // namespace cc
142
143#endif  // CC_RESOURCES_WORKER_POOL_H_
144