Index: base/task_scheduler/worker_thread.cc |
diff --git a/base/task_scheduler/worker_thread.cc b/base/task_scheduler/worker_thread.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..35f69bda8882b1aef0ff99a7660df9eea02f3565 |
--- /dev/null |
+++ b/base/task_scheduler/worker_thread.cc |
@@ -0,0 +1,90 @@ |
+// Copyright 2016 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. |
+ |
+#include "base/task_scheduler/worker_thread.h" |
+ |
+#include <stddef.h> |
+ |
+#include <utility> |
+ |
+#include "base/logging.h" |
+#include "base/task_scheduler/task_tracker.h" |
+ |
+namespace base { |
+namespace internal { |
+ |
+scoped_ptr<WorkerThread> WorkerThread::CreateWorkerThread( |
+ ThreadPriority thread_priority, |
+ const GetWorkCallback& get_work_callback, |
+ const RanTaskFromSequenceCallback& ran_task_from_sequence_callback, |
+ TaskTracker* task_tracker) { |
+ scoped_ptr<WorkerThread> worker_thread( |
+ new WorkerThread(thread_priority, get_work_callback, |
+ ran_task_from_sequence_callback, task_tracker)); |
+ |
+ if (worker_thread->thread_handle_.is_null()) |
+ return scoped_ptr<WorkerThread>(); |
danakj
2016/03/31 00:25:13
return nullptr
fdoray
2016/03/31 03:26:31
Done.
|
+ return worker_thread; |
+} |
+ |
+WorkerThread::~WorkerThread() { |
+ DCHECK(should_exit_for_testing()); |
+} |
+ |
+void WorkerThread::WakeUp() { |
+ wake_up_event_.Signal(); |
+} |
+ |
+void WorkerThread::JoinForTesting() { |
+ should_exit_for_testing_ = true; |
+ base::subtle::MemoryBarrier(); |
+ WakeUp(); |
+ PlatformThread::Join(thread_handle_); |
+} |
+ |
+WorkerThread::WorkerThread( |
+ ThreadPriority thread_priority, |
+ const GetWorkCallback& get_work_callback, |
+ const RanTaskFromSequenceCallback& ran_task_from_sequence_callback, |
+ TaskTracker* task_tracker) |
+ : wake_up_event_(false, false), |
+ get_work_callback_(get_work_callback), |
+ ran_task_from_sequence_callback_(ran_task_from_sequence_callback), |
+ task_tracker_(task_tracker) { |
+ DCHECK(!get_work_callback_.is_null()); |
+ DCHECK(!ran_task_from_sequence_callback_.is_null()); |
+ DCHECK(task_tracker_); |
+ |
+ static const size_t kDefaultStackSize = 0; |
+ PlatformThread::CreateWithPriority(kDefaultStackSize, this, &thread_handle_, |
+ thread_priority); |
+} |
+ |
+void WorkerThread::ThreadMain() { |
+ // A WorkerThread starts out sleeping. |
+ wake_up_event_.Wait(); |
+ |
+ while (!task_tracker_->shutdown_completed() && !should_exit_for_testing()) { |
+ // Get the sequence containing the next task to execute. |
+ scoped_refptr<Sequence> sequence = get_work_callback_.Run(this); |
+ |
+ if (!sequence) { |
+ wake_up_event_.Wait(); |
+ continue; |
+ } |
+ |
+ task_tracker_->RunTask(sequence->PeekTask()); |
+ ran_task_from_sequence_callback_.Run(this, std::move(sequence)); |
+ |
+ // Calling WakeUp() guarantees that this WorkerThread will run Tasks from |
+ // Sequences returned by |get_work_callback_| until the callback returns |
+ // nullptr. Resetting |wake_up_event_| here doesn't break this invariant and |
+ // avoids a useless loop iteration before going to sleep if WakeUp() is |
+ // called while this WorkerThread is awake. |
+ wake_up_event_.Reset(); |
+ } |
+} |
+ |
+} // namespace internal |
+} // namespace base |