background_command_transceiver.cc revision 30c921db09d27768acc1ea0d8b6a9c8e814f931a
1// 2// Copyright (C) 2015 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17#include "trunks/background_command_transceiver.h" 18 19#include <base/bind.h> 20#include <base/callback.h> 21#include <base/location.h> 22#include <base/logging.h> 23#include <base/single_thread_task_runner.h> 24#include <base/synchronization/waitable_event.h> 25#include <base/threading/thread_task_runner_handle.h> 26 27namespace { 28 29// A simple callback useful when waiting for an asynchronous call. 30void AssignAndSignal(std::string* destination, 31 base::WaitableEvent* event, 32 const std::string& source) { 33 *destination = source; 34 event->Signal(); 35} 36 37// A callback which posts another |callback| to a given |task_runner|. 38void PostCallbackToTaskRunner( 39 const trunks::CommandTransceiver::ResponseCallback& callback, 40 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 41 const std::string& response) { 42 base::Closure task = base::Bind(callback, response); 43 task_runner->PostTask(FROM_HERE, task); 44} 45 46} // namespace 47 48namespace trunks { 49 50BackgroundCommandTransceiver::BackgroundCommandTransceiver( 51 CommandTransceiver* next_transceiver, 52 const scoped_refptr<base::SequencedTaskRunner>& task_runner) 53 : next_transceiver_(next_transceiver), 54 task_runner_(task_runner), 55 weak_factory_(this) {} 56 57BackgroundCommandTransceiver::~BackgroundCommandTransceiver() {} 58 59void BackgroundCommandTransceiver::SendCommand( 60 const std::string& command, 61 const ResponseCallback& callback) { 62 if (task_runner_.get()) { 63 ResponseCallback background_callback = 64 base::Bind(PostCallbackToTaskRunner, callback, 65 base::ThreadTaskRunnerHandle::Get()); 66 // Use SendCommandTask instead of binding to next_transceiver_ directly to 67 // leverage weak pointer semantics. 68 base::Closure task = 69 base::Bind(&BackgroundCommandTransceiver::SendCommandTask, GetWeakPtr(), 70 command, background_callback); 71 task_runner_->PostNonNestableTask(FROM_HERE, task); 72 } else { 73 next_transceiver_->SendCommand(command, callback); 74 } 75} 76 77std::string BackgroundCommandTransceiver::SendCommandAndWait( 78 const std::string& command) { 79 if (task_runner_.get()) { 80 std::string response; 81 base::WaitableEvent response_ready(true, // manual_reset 82 false); // initially_signaled 83 ResponseCallback callback = 84 base::Bind(&AssignAndSignal, &response, &response_ready); 85 // Use SendCommandTask instead of binding to next_transceiver_ directly to 86 // leverage weak pointer semantics. 87 base::Closure task = 88 base::Bind(&BackgroundCommandTransceiver::SendCommandTask, GetWeakPtr(), 89 command, callback); 90 task_runner_->PostNonNestableTask(FROM_HERE, task); 91 response_ready.Wait(); 92 return response; 93 } else { 94 return next_transceiver_->SendCommandAndWait(command); 95 } 96} 97 98void BackgroundCommandTransceiver::SendCommandTask( 99 const std::string& command, 100 const ResponseCallback& callback) { 101 next_transceiver_->SendCommand(command, callback); 102} 103 104} // namespace trunks 105