OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 BASE_TASK_SCHEDULER_WORKER_THREAD_H_ |
| 6 #define BASE_TASK_SCHEDULER_WORKER_THREAD_H_ |
| 7 |
| 8 #include <iosfwd> |
| 9 |
| 10 #include "base/atomicops.h" |
| 11 #include "base/base_export.h" |
| 12 #include "base/callback.h" |
| 13 #include "base/macros.h" |
| 14 #include "base/memory/ref_counted.h" |
| 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/single_thread_task_runner.h" |
| 17 #include "base/synchronization/waitable_event.h" |
| 18 #include "base/task_scheduler/priority_queue.h" |
| 19 #include "base/task_scheduler/sequence.h" |
| 20 #include "base/task_scheduler/task_traits.h" |
| 21 #include "base/threading/platform_thread.h" |
| 22 |
| 23 namespace base { |
| 24 namespace internal { |
| 25 |
| 26 class TaskTracker; |
| 27 |
| 28 // A thread that runs Tasks from a shared and a single-threaded PriorityQueue. |
| 29 // |
| 30 // There is no guarantee that a WorkerThread will run work from its shared |
| 31 // PriorityQueue unless WakeUp() is called after the work is added. This allows |
| 32 // a ThreadPool to choose which WorkerThread should run the new work. On the |
| 33 // other hand, a WorkerThread is woken up automatically when Tasks are added to |
| 34 // its single-threaded PriorityQueue. |
| 35 // |
| 36 // This class is thread-safe. |
| 37 class BASE_EXPORT WorkerThread : public PlatformThread::Delegate { |
| 38 public: |
| 39 // Possible states for a WorkerThread. |
| 40 enum class State { |
| 41 BUSY, |
| 42 IDLE, |
| 43 }; |
| 44 |
| 45 // Callback invoked to indicate that a shared |sequence| is not empty after |
| 46 // |worker_thread| has popped a Task from it. |
| 47 using SharedSequenceStillHasTasksCallback = |
| 48 Callback<void(const WorkerThread* worker_thread, |
| 49 scoped_refptr<Sequence> sequence)>; |
| 50 |
| 51 // Callback invoked when the state of |worker_thread| becomes |state|. This is |
| 52 // always invoked within the scope of an active |shared_priority_queue_| |
| 53 // Transaction. If |state| is IDLE, it is guaranteed that |
| 54 // |shared_priority_queue_| is empty (this can't change during the callback |
| 55 // invocation because of the active Transaction). |
| 56 using StateChangedCallback = |
| 57 Callback<void(WorkerThread* worker_thread, State state)>; |
| 58 |
| 59 // Creates a WorkerThread with priority |thread_priority| that runs Tasks from |
| 60 // its single-threaded PriorityQueue and from |shared_priority_queue|. |
| 61 // |shared_sequence_still_has_tasks_callback| is invoked when a Sequence |
| 62 // extracted from |shared_priority_queue| isn't empty after the WorkerThread |
| 63 // has popped a task from it. |state_changed_callback| is invoked when the |
| 64 // WorkerThread becomes IDLE or BUSY. |task_tracker| is used to handle |
| 65 // shutdown behavior of Tasks. |
| 66 static scoped_ptr<WorkerThread> CreateWorkerThread( |
| 67 ThreadPriority thread_priority, |
| 68 PriorityQueue* shared_priority_queue, |
| 69 const SharedSequenceStillHasTasksCallback& |
| 70 shared_sequence_still_has_tasks_callback, |
| 71 const StateChangedCallback& state_changed_callback, |
| 72 TaskTracker* task_tracker); |
| 73 |
| 74 // Destroying a WorkerThread in production is not allowed; it is always |
| 75 // leaked. In tests, it can only be destroyed after JoinForTesting() has |
| 76 // returned. |
| 77 ~WorkerThread() override; |
| 78 |
| 79 // Wakes up this WorkerThread. When this is called, this WorkerThread will run |
| 80 // until both its PriorityQueues become empty. |
| 81 void WakeUp(); |
| 82 |
| 83 // Returns a SingleThreadTaskRunner whose PostTask invocations will result in |
| 84 // scheduling Tasks with |traits| on this WorkerThread. |
| 85 scoped_refptr<SingleThreadTaskRunner> CreateTaskRunnerWithTraits( |
| 86 const TaskTraits& traits); |
| 87 |
| 88 // Joins this WorkerThread. If a Task is already running, it will be allowed |
| 89 // to complete its execution. This can only be called once. |
| 90 void JoinForTesting(); |
| 91 |
| 92 private: |
| 93 WorkerThread(ThreadPriority thread_priority, |
| 94 PriorityQueue* shared_priority_queue, |
| 95 const SharedSequenceStillHasTasksCallback& |
| 96 shared_sequence_still_has_tasks_callback, |
| 97 const StateChangedCallback& state_changed_callback, |
| 98 TaskTracker* task_tracker); |
| 99 |
| 100 // Sets the state of this WorkerThread. |
| 101 void SetState(State state); |
| 102 |
| 103 // PlatformThread::Delegate: |
| 104 void ThreadMain() override; |
| 105 |
| 106 bool should_exit_for_testing() const { |
| 107 base::subtle::MemoryBarrier(); |
| 108 return should_exit_for_testing_; |
| 109 } |
| 110 |
| 111 // Platform thread managed by this WorkerThread. |
| 112 PlatformThreadHandle thread_handle_; |
| 113 |
| 114 // Current state of this WorkerThread. |
| 115 State state_ = State::BUSY; |
| 116 |
| 117 // Event signaled to wake up this WorkerThread. |
| 118 WaitableEvent wake_up_event_; |
| 119 |
| 120 // The single-threaded PriorityQueue from which this WorkerThread gets work. |
| 121 PriorityQueue single_thread_priority_queue_; |
| 122 |
| 123 // The shared PriorityQueue from which this WorkerThread gets work. |
| 124 PriorityQueue* const shared_priority_queue_; |
| 125 |
| 126 const SharedSequenceStillHasTasksCallback |
| 127 shared_sequence_still_has_tasks_callback_; |
| 128 const StateChangedCallback state_changed_callback_; |
| 129 TaskTracker* const task_tracker_; |
| 130 |
| 131 // True once JoinForTesting() has been called. |
| 132 bool should_exit_for_testing_ = false; |
| 133 |
| 134 DISALLOW_COPY_AND_ASSIGN(WorkerThread); |
| 135 }; |
| 136 |
| 137 BASE_EXPORT std::ostream& operator<<(std::ostream& os, |
| 138 WorkerThread::State state); |
| 139 |
| 140 } // namespace internal |
| 141 } // namespace base |
| 142 |
| 143 #endif // BASE_TASK_SCHEDULER_WORKER_THREAD_H_ |
OLD | NEW |