105 lines
3.6 KiB
C++
105 lines
3.6 KiB
C++
//
|
|
// 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
|