Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: base/test/scoped_task_scheduler.cc

Issue 2768873007: Add Support to Get a COM STA Task Runner from the Task Scheduler API (Closed)
Patch Set: CR Feedback Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/test/scoped_task_scheduler.h" 5 #include "base/test/scoped_task_scheduler.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
15 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram_base.h" 16 #include "base/metrics/histogram_base.h"
17 #include "base/run_loop.h" 17 #include "base/run_loop.h"
18 #include "base/sequence_token.h" 18 #include "base/sequence_token.h"
19 #include "base/sequenced_task_runner.h" 19 #include "base/sequenced_task_runner.h"
20 #include "base/single_thread_task_runner.h" 20 #include "base/single_thread_task_runner.h"
21 #include "base/task_runner.h" 21 #include "base/task_runner.h"
22 #include "base/task_scheduler/task.h" 22 #include "base/task_scheduler/task.h"
23 #include "base/task_scheduler/task_scheduler.h" 23 #include "base/task_scheduler/task_scheduler.h"
24 #include "base/task_scheduler/task_tracker.h" 24 #include "base/task_scheduler/task_tracker.h"
25 #include "base/threading/thread_task_runner_handle.h" 25 #include "base/threading/thread_task_runner_handle.h"
26 #include "base/time/time.h"
27 #include "build/build_config.h"
28
29 #if defined(OS_WIN)
30 #include "base/win/scoped_com_initializer.h"
31 #endif // defined(OS_WIN)
26 32
27 namespace base { 33 namespace base {
28 namespace test { 34 namespace test {
29 35
30 namespace { 36 namespace {
31 37
32 enum class ExecutionMode { PARALLEL, SEQUENCED, SINGLE_THREADED }; 38 enum class ExecutionMode { PARALLEL, SEQUENCED, SINGLE_THREADED };
33 39
34 class TestTaskScheduler : public TaskScheduler { 40 class TestTaskScheduler : public TaskScheduler {
35 public: 41 public:
36 // |external_message_loop| is an externally provided MessageLoop on which to 42 // |external_message_loop| is an externally provided MessageLoop on which to
37 // run tasks. A MessageLoop will be created by TestTaskScheduler if 43 // run tasks. A MessageLoop will be created by TestTaskScheduler if
38 // |external_message_loop| is nullptr. 44 // |external_message_loop| is nullptr.
39 explicit TestTaskScheduler(MessageLoop* external_message_loop); 45 explicit TestTaskScheduler(MessageLoop* external_message_loop);
40 ~TestTaskScheduler() override; 46 ~TestTaskScheduler() override;
41 47
42 // TaskScheduler: 48 // TaskScheduler:
43 void PostDelayedTaskWithTraits(const tracked_objects::Location& from_here, 49 void PostDelayedTaskWithTraits(const tracked_objects::Location& from_here,
44 const TaskTraits& traits, 50 const TaskTraits& traits,
45 const Closure& task, 51 const Closure& task,
46 TimeDelta delay) override; 52 TimeDelta delay) override;
47 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits( 53 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
48 const TaskTraits& traits) override; 54 const TaskTraits& traits) override;
49 scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits( 55 scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
50 const TaskTraits& traits) override; 56 const TaskTraits& traits) override;
51 scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits( 57 scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits(
52 const TaskTraits& traits) override; 58 const TaskTraits& traits) override;
59 #if defined(OS_WIN)
60 scoped_refptr<SingleThreadTaskRunner> CreateCOMSTATaskRunnerWithTraits(
61 const TaskTraits& traits) override;
62 #endif // defined(OS_WIN)
53 std::vector<const HistogramBase*> GetHistograms() const override; 63 std::vector<const HistogramBase*> GetHistograms() const override;
54 int GetMaxConcurrentTasksWithTraitsDeprecated( 64 int GetMaxConcurrentTasksWithTraitsDeprecated(
55 const TaskTraits& traits) const override; 65 const TaskTraits& traits) const override;
56 void Shutdown() override; 66 void Shutdown() override;
57 void FlushForTesting() override; 67 void FlushForTesting() override;
58 void JoinForTesting() override; 68 void JoinForTesting() override;
59 69
60 // Posts |task| to this TaskScheduler with |sequence_token|. Returns true on 70 // Posts |task| to this TaskScheduler with |sequence_token|. Returns true on
61 // success. 71 // success.
62 bool PostTask(std::unique_ptr<internal::Task> task, 72 bool PostTask(std::unique_ptr<internal::Task> task,
(...skipping 10 matching lines...) Expand all
73 // Returns the TaskRunner to which this TaskScheduler forwards tasks. It may 83 // Returns the TaskRunner to which this TaskScheduler forwards tasks. It may
74 // be |message_loop_->task_runner()| or a reference to it saved on entry to 84 // be |message_loop_->task_runner()| or a reference to it saved on entry to
75 // RunTask(). 85 // RunTask().
76 scoped_refptr<SingleThreadTaskRunner> MessageLoopTaskRunner() const { 86 scoped_refptr<SingleThreadTaskRunner> MessageLoopTaskRunner() const {
77 if (saved_task_runner_) 87 if (saved_task_runner_)
78 return saved_task_runner_; 88 return saved_task_runner_;
79 DCHECK(message_loop_->task_runner()); 89 DCHECK(message_loop_->task_runner());
80 return message_loop_->task_runner(); 90 return message_loop_->task_runner();
81 } 91 }
82 92
93 #if defined(OS_WIN)
94 void EnsureCOMSTA() {
95 if (!com_init_requested) {
96 com_init_requested = true;
97 DCHECK(!scoped_com_initializer_);
98 PostTask(MakeUnique<internal::Task>(
99 FROM_HERE,
100 Bind(
101 [](std::unique_ptr<win::ScopedCOMInitializer>*
102 scoped_com_initializer) {
103 DCHECK(!*scoped_com_initializer);
104 *scoped_com_initializer =
105 MakeUnique<win::ScopedCOMInitializer>();
106 },
107 &scoped_com_initializer_),
108 TaskTraits(), TimeDelta()),
109 SequenceToken());
110 }
111 }
112 #endif // defined(OS_WIN)
113
83 // |message_loop_owned_| will be non-null if this TestTaskScheduler owns the 114 // |message_loop_owned_| will be non-null if this TestTaskScheduler owns the
84 // MessageLoop (wasn't provided an external one at construction). 115 // MessageLoop (wasn't provided an external one at construction).
85 // |message_loop_| will always be set and is used by this TestTaskScheduler to 116 // |message_loop_| will always be set and is used by this TestTaskScheduler to
86 // run tasks. 117 // run tasks.
87 std::unique_ptr<MessageLoop> message_loop_owned_; 118 std::unique_ptr<MessageLoop> message_loop_owned_;
88 MessageLoop* message_loop_; 119 MessageLoop* message_loop_;
89 120
90 // A reference to |message_loop_->task_runner()| saved on entry to RunTask(). 121 // A reference to |message_loop_->task_runner()| saved on entry to RunTask().
91 // This is required because RunTask() overrides 122 // This is required because RunTask() overrides
92 // |message_loop_->task_runner()|. 123 // |message_loop_->task_runner()|.
93 // 124 //
94 // Note: |message_loop_->task_runner()| is accessed directly outside of 125 // Note: |message_loop_->task_runner()| is accessed directly outside of
95 // RunTask() to guarantee that ScopedTaskScheduler always uses the latest 126 // RunTask() to guarantee that ScopedTaskScheduler always uses the latest
96 // TaskRunner set by external code. 127 // TaskRunner set by external code.
97 scoped_refptr<SingleThreadTaskRunner> saved_task_runner_; 128 scoped_refptr<SingleThreadTaskRunner> saved_task_runner_;
98 129
130 #if defined(OS_WIN)
131 // Maintains the lifetime of the COM Single-Threaded Apartment. Allocation and
132 // deallocation should be done in the |message_loop_| via PostTask.
133 std::unique_ptr<win::ScopedCOMInitializer> scoped_com_initializer_;
134
135 bool com_init_requested = false;
136 #endif // defined(OS_WIN)
137
99 // Handles shutdown behaviors and sets up the environment to run a task. 138 // Handles shutdown behaviors and sets up the environment to run a task.
100 internal::TaskTracker task_tracker_; 139 internal::TaskTracker task_tracker_;
101 140
102 DISALLOW_COPY_AND_ASSIGN(TestTaskScheduler); 141 DISALLOW_COPY_AND_ASSIGN(TestTaskScheduler);
103 }; 142 };
104 143
105 class TestTaskSchedulerTaskRunner : public SingleThreadTaskRunner { 144 class TestTaskSchedulerTaskRunner : public SingleThreadTaskRunner {
106 public: 145 public:
107 TestTaskSchedulerTaskRunner(TestTaskScheduler* task_scheduler, 146 TestTaskSchedulerTaskRunner(TestTaskScheduler* task_scheduler,
108 ExecutionMode execution_mode, 147 ExecutionMode execution_mode,
(...skipping 22 matching lines...) Expand all
131 TestTaskScheduler::TestTaskScheduler(MessageLoop* external_message_loop) 170 TestTaskScheduler::TestTaskScheduler(MessageLoop* external_message_loop)
132 : message_loop_owned_(external_message_loop ? nullptr 171 : message_loop_owned_(external_message_loop ? nullptr
133 : MakeUnique<MessageLoop>()), 172 : MakeUnique<MessageLoop>()),
134 message_loop_(message_loop_owned_ ? message_loop_owned_.get() 173 message_loop_(message_loop_owned_ ? message_loop_owned_.get()
135 : external_message_loop) {} 174 : external_message_loop) {}
136 175
137 TestTaskScheduler::~TestTaskScheduler() { 176 TestTaskScheduler::~TestTaskScheduler() {
138 // Shutdown if it hasn't already been done explicitly. 177 // Shutdown if it hasn't already been done explicitly.
139 if (!task_tracker_.HasShutdownStarted()) 178 if (!task_tracker_.HasShutdownStarted())
140 Shutdown(); 179 Shutdown();
180
181 #if defined(OS_WIN)
182 MessageLoopTaskRunner()->PostTask(
183 FROM_HERE,
184 Bind([](std::unique_ptr<win::ScopedCOMInitializer>*
185 scoped_com_initializer) { scoped_com_initializer->reset(); },
186 &scoped_com_initializer_));
187
188 RunLoop().RunUntilIdle();
fdoray 2017/03/28 14:14:46 RunLoop().RunUntilIdle() runs tasks on the current
robliao 2017/03/28 17:15:01 Yeah, Shutdown() seemed pretty strange to me when
189
190 DCHECK(!scoped_com_initializer_);
191 #endif // defined(OS_WIN)
141 } 192 }
142 193
143 void TestTaskScheduler::PostDelayedTaskWithTraits( 194 void TestTaskScheduler::PostDelayedTaskWithTraits(
144 const tracked_objects::Location& from_here, 195 const tracked_objects::Location& from_here,
145 const TaskTraits& traits, 196 const TaskTraits& traits,
146 const Closure& task, 197 const Closure& task,
147 TimeDelta delay) { 198 TimeDelta delay) {
148 CreateTaskRunnerWithTraits(traits)->PostDelayedTask(from_here, task, delay); 199 CreateTaskRunnerWithTraits(traits)->PostDelayedTask(from_here, task, delay);
149 } 200 }
150 201
(...skipping 10 matching lines...) Expand all
161 new TestTaskSchedulerTaskRunner(this, ExecutionMode::SEQUENCED, traits)); 212 new TestTaskSchedulerTaskRunner(this, ExecutionMode::SEQUENCED, traits));
162 } 213 }
163 214
164 scoped_refptr<SingleThreadTaskRunner> 215 scoped_refptr<SingleThreadTaskRunner>
165 TestTaskScheduler::CreateSingleThreadTaskRunnerWithTraits( 216 TestTaskScheduler::CreateSingleThreadTaskRunnerWithTraits(
166 const TaskTraits& traits) { 217 const TaskTraits& traits) {
167 return make_scoped_refptr(new TestTaskSchedulerTaskRunner( 218 return make_scoped_refptr(new TestTaskSchedulerTaskRunner(
168 this, ExecutionMode::SINGLE_THREADED, traits)); 219 this, ExecutionMode::SINGLE_THREADED, traits));
169 } 220 }
170 221
222 #if defined(OS_WIN)
223 scoped_refptr<SingleThreadTaskRunner>
224 TestTaskScheduler::CreateCOMSTATaskRunnerWithTraits(const TaskTraits& traits) {
225 EnsureCOMSTA();
226 return make_scoped_refptr(new TestTaskSchedulerTaskRunner(
227 this, ExecutionMode::SINGLE_THREADED, traits));
228 }
229 #endif // defined(OS_WIN)
230
171 std::vector<const HistogramBase*> TestTaskScheduler::GetHistograms() const { 231 std::vector<const HistogramBase*> TestTaskScheduler::GetHistograms() const {
172 NOTREACHED(); 232 NOTREACHED();
173 return std::vector<const HistogramBase*>(); 233 return std::vector<const HistogramBase*>();
174 } 234 }
175 235
176 int TestTaskScheduler::GetMaxConcurrentTasksWithTraitsDeprecated( 236 int TestTaskScheduler::GetMaxConcurrentTasksWithTraitsDeprecated(
177 const TaskTraits& traits) const { 237 const TaskTraits& traits) const {
178 return 1; 238 return 1;
179 } 239 }
180 240
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 DCHECK_EQ(task_scheduler_, TaskScheduler::GetInstance()); 347 DCHECK_EQ(task_scheduler_, TaskScheduler::GetInstance());
288 348
289 // Per contract, call JoinForTesting() before deleting the TaskScheduler. 349 // Per contract, call JoinForTesting() before deleting the TaskScheduler.
290 TaskScheduler::GetInstance()->JoinForTesting(); 350 TaskScheduler::GetInstance()->JoinForTesting();
291 351
292 TaskScheduler::SetInstance(nullptr); 352 TaskScheduler::SetInstance(nullptr);
293 } 353 }
294 354
295 } // namespace test 355 } // namespace test
296 } // namespace base 356 } // namespace base
OLDNEW
« no previous file with comments | « base/task_scheduler/task_scheduler_impl_unittest.cc ('k') | base/test/scoped_task_scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698