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

Side by Side Diff: media/gpu/avda_codec_allocator.cc

Issue 2540593005: media: Fix a flaky AVDACodecAllocator test (Closed)
Patch Set: Add dep for test clock Created 4 years 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
« no previous file with comments | « media/gpu/avda_codec_allocator.h ('k') | media/gpu/avda_codec_allocator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "media/gpu/avda_codec_allocator.h" 5 #include "media/gpu/avda_codec_allocator.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 codec.reset(); 42 codec.reset();
43 if (done_event) 43 if (done_event)
44 done_event->Signal(); 44 done_event->Signal();
45 } 45 }
46 46
47 } // namespace 47 } // namespace
48 48
49 CodecConfig::CodecConfig() {} 49 CodecConfig::CodecConfig() {}
50 CodecConfig::~CodecConfig() {} 50 CodecConfig::~CodecConfig() {}
51 51
52 AVDACodecAllocator::TestInformation::TestInformation() {}
53 AVDACodecAllocator::TestInformation::~TestInformation() {}
54
55 AVDACodecAllocator::HangDetector::HangDetector(base::TickClock* tick_clock) 52 AVDACodecAllocator::HangDetector::HangDetector(base::TickClock* tick_clock)
56 : tick_clock_(tick_clock) {} 53 : tick_clock_(tick_clock) {}
57 54
58 void AVDACodecAllocator::HangDetector::WillProcessTask( 55 void AVDACodecAllocator::HangDetector::WillProcessTask(
59 const base::PendingTask& pending_task) { 56 const base::PendingTask& pending_task) {
60 base::AutoLock l(lock_); 57 base::AutoLock l(lock_);
61 task_start_time_ = tick_clock_->NowTicks(); 58 task_start_time_ = tick_clock_->NowTicks();
62 } 59 }
63 60
64 void AVDACodecAllocator::HangDetector::DidProcessTask( 61 void AVDACodecAllocator::HangDetector::DidProcessTask(
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 return false; 110 return false;
114 111
115 clients_.insert(client); 112 clients_.insert(client);
116 return true; 113 return true;
117 } 114 }
118 115
119 void AVDACodecAllocator::StopThread(AVDACodecAllocatorClient* client) { 116 void AVDACodecAllocator::StopThread(AVDACodecAllocatorClient* client) {
120 DCHECK(thread_checker_.CalledOnValidThread()); 117 DCHECK(thread_checker_.CalledOnValidThread());
121 118
122 clients_.erase(client); 119 clients_.erase(client);
120 if (!clients_.empty()) {
121 // If we aren't stopping, then signal immediately.
122 if (stop_event_for_testing_)
123 stop_event_for_testing_->Signal();
124 return;
125 }
126
123 // Post a task to stop the thread through the thread's task runner and back 127 // Post a task to stop the thread through the thread's task runner and back
124 // to this thread. This ensures that all pending tasks are run first. If the 128 // to this thread. This ensures that all pending tasks are run first. If the
125 // thread is hung we don't post a task to avoid leaking an unbounded number 129 // thread is hung we don't post a task to avoid leaking an unbounded number
126 // of tasks on its queue. If the thread is not hung, but appears to be, it 130 // of tasks on its queue. If the thread is not hung, but appears to be, it
127 // will stay alive until next time an AVDA tries to stop it. We're 131 // will stay alive until next time an AVDA tries to stop it. We're
128 // guaranteed to not run StopThreadTask() when the thread is hung because if 132 // guaranteed to not run StopThreadTask() when the thread is hung because if
129 // an AVDA queues tasks after DoNothing(), the StopThreadTask() reply will 133 // an AVDA queues tasks after DoNothing(), the StopThreadTask() reply will
130 // be canceled by invalidating its weak pointer. 134 // be canceled by invalidating its weak pointer.
131 base::WaitableEvent* event =
132 (test_info_ ? test_info_->stop_event_.get() : nullptr);
133 if (!clients_.empty()) {
134 // If we aren't stopping, then signal immediately.
135 if (event)
136 event->Signal();
137 return;
138 }
139
140 for (size_t i = 0; i < threads_.size(); i++) { 135 for (size_t i = 0; i < threads_.size(); i++) {
141 if (threads_[i]->thread.IsRunning() && 136 if (threads_[i]->thread.IsRunning() &&
142 !threads_[i]->hang_detector.IsThreadLikelyHung()) { 137 !threads_[i]->hang_detector.IsThreadLikelyHung()) {
143 threads_[i]->thread.task_runner()->PostTaskAndReply( 138 threads_[i]->thread.task_runner()->PostTaskAndReply(
144 FROM_HERE, base::Bind(&base::DoNothing), 139 FROM_HERE, base::Bind(&base::DoNothing),
145 base::Bind(&AVDACodecAllocator::StopThreadTask, 140 base::Bind(
146 weak_this_factory_.GetWeakPtr(), i, 141 &AVDACodecAllocator::StopThreadTask,
147 (i == TaskType::AUTO_CODEC ? event : nullptr))); 142 weak_this_factory_.GetWeakPtr(), i,
143 (i == TaskType::AUTO_CODEC ? stop_event_for_testing_ : nullptr)));
148 } 144 }
149 } 145 }
150 } 146 }
151 147
152 // Return the task runner for tasks of type |type|. If that thread failed 148 // Return the task runner for tasks of type |type|. If that thread failed
153 // to start, then fall back to the GPU main thread. 149 // to start, then fall back to the GPU main thread.
154 scoped_refptr<base::SingleThreadTaskRunner> AVDACodecAllocator::TaskRunnerFor( 150 scoped_refptr<base::SingleThreadTaskRunner> AVDACodecAllocator::TaskRunnerFor(
155 TaskType task_type) { 151 TaskType task_type) {
156 DCHECK(thread_checker_.CalledOnValidThread()); 152 DCHECK(thread_checker_.CalledOnValidThread());
157 base::Thread& thread = threads_[task_type]->thread; 153 base::Thread& thread = threads_[task_type]->thread;
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 return TaskType::SW_CODEC; 359 return TaskType::SW_CODEC;
364 360
365 // If nothing is working, then we can't allocate anyway. 361 // If nothing is working, then we can't allocate anyway.
366 return TaskType::FAILED_CODEC; 362 return TaskType::FAILED_CODEC;
367 } 363 }
368 364
369 base::Thread& AVDACodecAllocator::GetThreadForTesting(TaskType task_type) { 365 base::Thread& AVDACodecAllocator::GetThreadForTesting(TaskType task_type) {
370 return threads_[task_type]->thread; 366 return threads_[task_type]->thread;
371 } 367 }
372 368
373 AVDACodecAllocator::AVDACodecAllocator(TestInformation* test_info) 369 AVDACodecAllocator::AVDACodecAllocator(base::TickClock* tick_clock,
374 : test_info_(test_info), weak_this_factory_(this) { 370 base::WaitableEvent* stop_event)
375 // If we're not provided with one, use real time. 371 : stop_event_for_testing_(stop_event), weak_this_factory_(this) {
376 // Note that we'll leak this, but that's okay since we're a singleton. 372 // We leak the clock we create, but that's okay because we're a singleton.
377 base::TickClock* tick_clock = nullptr; 373 auto clock = tick_clock ? tick_clock : new base::DefaultTickClock();
378 if (!test_info_)
379 tick_clock = new base::DefaultTickClock();
380 else
381 tick_clock = test_info_->tick_clock_.get();
382 374
383 // Create threads with names / indices that match up with TaskType. 375 // Create threads with names / indices that match up with TaskType.
384 DCHECK_EQ(threads_.size(), TaskType::AUTO_CODEC); 376 DCHECK_EQ(threads_.size(), TaskType::AUTO_CODEC);
385 threads_.push_back(new ThreadAndHangDetector("AVDAAutoThread", tick_clock)); 377 threads_.push_back(new ThreadAndHangDetector("AVDAAutoThread", clock));
386 DCHECK_EQ(threads_.size(), TaskType::SW_CODEC); 378 DCHECK_EQ(threads_.size(), TaskType::SW_CODEC);
387 threads_.push_back(new ThreadAndHangDetector("AVDASWThread", tick_clock)); 379 threads_.push_back(new ThreadAndHangDetector("AVDASWThread", clock));
388 } 380 }
389 381
390 AVDACodecAllocator::~AVDACodecAllocator() { 382 AVDACodecAllocator::~AVDACodecAllocator() {
391 // Only tests should reach here. Shut down threads so that we guarantee that 383 // Only tests should reach here. Shut down threads so that we guarantee that
392 // nothing will use the threads. 384 // nothing will use the threads.
393 for (size_t i = 0; i < threads_.size(); i++) { 385 for (size_t i = 0; i < threads_.size(); i++) {
394 if (!threads_[i]->thread.IsRunning()) 386 if (!threads_[i]->thread.IsRunning())
395 continue; 387 continue;
396 threads_[i]->thread.Stop(); 388 threads_[i]->thread.Stop();
397 } 389 }
398 } 390 }
399 391
400 void AVDACodecAllocator::StopThreadTask(size_t index, 392 void AVDACodecAllocator::StopThreadTask(size_t index,
401 base::WaitableEvent* event) { 393 base::WaitableEvent* event) {
402 threads_[index]->thread.Stop(); 394 threads_[index]->thread.Stop();
403 if (event) 395 if (event)
404 event->Signal(); 396 event->Signal();
405 } 397 }
406 398
407 } // namespace media 399 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/avda_codec_allocator.h ('k') | media/gpu/avda_codec_allocator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698