You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.6 KiB
105 lines
3.6 KiB
// |
|
// Copyright (C) 2015 The Android Open Source Project |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
// you may not use this file except in compliance with the License. |
|
// You may obtain a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, |
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
// See the License for the specific language governing permissions and |
|
// limitations under the License. |
|
// |
|
|
|
#include "trunks/background_command_transceiver.h" |
|
|
|
#include <base/bind.h> |
|
#include <base/callback.h> |
|
#include <base/location.h> |
|
#include <base/logging.h> |
|
#include <base/single_thread_task_runner.h> |
|
#include <base/synchronization/waitable_event.h> |
|
#include <base/threading/thread_task_runner_handle.h> |
|
|
|
namespace { |
|
|
|
// A simple callback useful when waiting for an asynchronous call. |
|
void AssignAndSignal(std::string* destination, |
|
base::WaitableEvent* event, |
|
const std::string& source) { |
|
*destination = source; |
|
event->Signal(); |
|
} |
|
|
|
// A callback which posts another |callback| to a given |task_runner|. |
|
void PostCallbackToTaskRunner( |
|
const trunks::CommandTransceiver::ResponseCallback& callback, |
|
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
|
const std::string& response) { |
|
base::Closure task = base::Bind(callback, response); |
|
task_runner->PostTask(FROM_HERE, task); |
|
} |
|
|
|
} // namespace |
|
|
|
namespace trunks { |
|
|
|
BackgroundCommandTransceiver::BackgroundCommandTransceiver( |
|
CommandTransceiver* next_transceiver, |
|
const scoped_refptr<base::SequencedTaskRunner>& task_runner) |
|
: next_transceiver_(next_transceiver), |
|
task_runner_(task_runner), |
|
weak_factory_(this) {} |
|
|
|
BackgroundCommandTransceiver::~BackgroundCommandTransceiver() {} |
|
|
|
void BackgroundCommandTransceiver::SendCommand( |
|
const std::string& command, |
|
const ResponseCallback& callback) { |
|
if (task_runner_.get()) { |
|
ResponseCallback background_callback = |
|
base::Bind(PostCallbackToTaskRunner, callback, |
|
base::ThreadTaskRunnerHandle::Get()); |
|
// Use SendCommandTask instead of binding to next_transceiver_ directly to |
|
// leverage weak pointer semantics. |
|
base::Closure task = |
|
base::Bind(&BackgroundCommandTransceiver::SendCommandTask, GetWeakPtr(), |
|
command, background_callback); |
|
task_runner_->PostNonNestableTask(FROM_HERE, task); |
|
} else { |
|
next_transceiver_->SendCommand(command, callback); |
|
} |
|
} |
|
|
|
std::string BackgroundCommandTransceiver::SendCommandAndWait( |
|
const std::string& command) { |
|
if (task_runner_.get()) { |
|
std::string response; |
|
base::WaitableEvent response_ready( |
|
base::WaitableEvent::ResetPolicy::MANUAL, |
|
base::WaitableEvent::InitialState::NOT_SIGNALED); |
|
ResponseCallback callback = |
|
base::Bind(&AssignAndSignal, &response, &response_ready); |
|
// Use SendCommandTask instead of binding to next_transceiver_ directly to |
|
// leverage weak pointer semantics. |
|
base::Closure task = |
|
base::Bind(&BackgroundCommandTransceiver::SendCommandTask, GetWeakPtr(), |
|
command, callback); |
|
task_runner_->PostNonNestableTask(FROM_HERE, task); |
|
response_ready.Wait(); |
|
return response; |
|
} else { |
|
return next_transceiver_->SendCommandAndWait(command); |
|
} |
|
} |
|
|
|
void BackgroundCommandTransceiver::SendCommandTask( |
|
const std::string& command, |
|
const ResponseCallback& callback) { |
|
next_transceiver_->SendCommand(command, callback); |
|
} |
|
|
|
} // namespace trunks
|
|
|