15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/serial_runner.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/single_thread_task_runner.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Converts a Closure into a bound function accepting a PipelineStatusCB. 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static void RunClosure( 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::Closure& closure, 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const PipelineStatusCB& status_cb) { 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) closure.Run(); 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) status_cb.Run(PIPELINE_OK); 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts a bound function accepting a Closure into a bound function 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accepting a PipelineStatusCB. Since closures have no way of reporting a 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// status |status_cb| is executed with PIPELINE_OK. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunBoundClosure( 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SerialRunner::BoundClosure& bound_closure, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PipelineStatusCB& status_cb) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_closure.Run(base::Bind(status_cb, PIPELINE_OK)); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Runs |status_cb| with |last_status| on |task_runner|. 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void RunOnTaskRunner( 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PipelineStatusCB& status_cb, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PipelineStatus last_status) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force post to permit cancellation of a series in the scenario where all 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bound functions run on the same thread. 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_runner->PostTask(FROM_HERE, base::Bind(status_cb, last_status)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SerialRunner::Queue::Queue() {} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SerialRunner::Queue::~Queue() {} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SerialRunner::Queue::Push(const base::Closure& closure) { 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bound_fns_.push(base::Bind(&RunClosure, closure)); 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SerialRunner::Queue::Push( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundClosure& bound_closure) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_fns_.push(base::Bind(&RunBoundClosure, bound_closure)); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SerialRunner::Queue::Push( 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundPipelineStatusCB& bound_status_cb) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_fns_.push(bound_status_cb); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SerialRunner::BoundPipelineStatusCB SerialRunner::Queue::Pop() { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BoundPipelineStatusCB bound_fn = bound_fns_.front(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_fns_.pop(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bound_fn; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SerialRunner::Queue::empty() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bound_fns_.empty(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)SerialRunner::SerialRunner(const Queue& bound_fns, 7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const PipelineStatusCB& done_cb) 7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) : task_runner_(base::MessageLoopProxy::current()), 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_fns_(bound_fns), 7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) done_cb_(done_cb), 7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) weak_factory_(this) { 75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Respect both cancellation and calling stack guarantees for |done_cb| 76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // when empty. 77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (bound_fns_.empty()) { 7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) task_runner_->PostTask(FROM_HERE, 7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Bind(&SerialRunner::RunNextInSeries, 8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) weak_factory_.GetWeakPtr(), 8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) PIPELINE_OK)); 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) RunNextInSeries(PIPELINE_OK); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SerialRunner::~SerialRunner() {} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<SerialRunner> SerialRunner::Run( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Queue& bound_fns, const PipelineStatusCB& done_cb) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SerialRunner> callback_series( 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SerialRunner(bound_fns, done_cb)); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return callback_series.Pass(); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SerialRunner::RunNextInSeries(PipelineStatus last_status) { 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!done_cb_.is_null()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bound_fns_.empty() || last_status != PIPELINE_OK) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ResetAndReturn(&done_cb_).Run(last_status); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BoundPipelineStatusCB bound_fn = bound_fns_.Pop(); 10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) bound_fn.Run(base::Bind( 10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &RunOnTaskRunner, 10923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) task_runner_, 11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Bind(&SerialRunner::RunNextInSeries, weak_factory_.GetWeakPtr()))); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 114