blob: d1c3ccaa0dc59716417ac9c24b845b9d34d0fd76 [file] [log] [blame]
/*
* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef CAMERA_INCLUDE_CROS_CAMERA_CAMERA_THREAD_H_
#define CAMERA_INCLUDE_CROS_CAMERA_CAMERA_THREAD_H_
#include <string>
#include <unordered_map>
#include <utility>
#include <base/location.h>
#include <base/threading/thread.h>
#include "cros-camera/common.h"
#include "cros-camera/export.h"
#include "cros-camera/future.h"
namespace cros {
class CROS_CAMERA_EXPORT CameraThread {
public:
explicit CameraThread(std::string name) : thread_(name) {}
CameraThread(const CameraThread&) = delete;
CameraThread& operator=(const CameraThread&) = delete;
// Starts the thread. Returns true if the thread was successfully started.
bool Start() {
if (!thread_.Start()) {
LOG(ERROR) << "Failed to start thread";
return false;
}
thread_.WaitUntilThreadStarted();
return true;
}
// Stop the thread. This function is expected to be called explicitly. A fatal
// error would have occured in the AtExitManager if it were called in
// the destructor.
void Stop() { thread_.Stop(); }
// Returns true if this is the current thread that is running.
bool IsCurrentThread() const {
return thread_.GetThreadId() == base::PlatformThread::CurrentId();
}
// Posts the given task to be run and wait till it is finished. The reply
// from callee will be stored in |result|. Return 0 if succeed. Otherwise
// return -EIO.
template <typename T>
int PostTaskSync(const base::Location& from_here,
base::OnceCallback<T()> task,
T* result) {
VLOGF_ENTER();
if (!thread_.task_runner()) {
LOG(ERROR) << "Thread is not started";
return -EIO;
}
auto future = cros::Future<T>::Create(nullptr);
base::OnceClosure closure =
base::BindOnce(&CameraThread::ProcessSyncTaskOnThread<T>,
base::Unretained(this), std::move(task), future);
if (!thread_.task_runner()->PostTask(from_here, std::move(closure))) {
LOG(ERROR) << "Failed to post task";
return -EIO;
}
*result = future->Get();
return 0;
}
// Posts the given task to be run asynchronously. Return 0 if succeed.
// Otherwise return -EIO.
template <typename T>
int PostTaskAsync(const base::Location& from_here,
base::OnceCallback<T()> task) {
VLOGF_ENTER();
if (!thread_.task_runner()) {
LOG(ERROR) << "Thread is not started";
return -EIO;
}
base::OnceClosure closure =
base::BindOnce(&CameraThread::ProcessASyncTaskOnThread<T>,
base::Unretained(this), std::move(task));
if (!thread_.task_runner()->PostTask(from_here, std::move(closure))) {
LOG(ERROR) << "Failed to post task";
return -EIO;
}
return 0;
}
// Posts the given task to be run and wait till it is finished.
// Return 0 if succeed. Otherwise return -EIO.
int PostTaskSync(const base::Location& from_here, base::OnceClosure task) {
VLOGF_ENTER();
if (!thread_.task_runner()) {
LOG(ERROR) << "Thread is not started";
return -EIO;
}
auto future = cros::Future<void>::Create(nullptr);
base::OnceClosure closure =
base::BindOnce(&CameraThread::ProcessClosureSyncTaskOnThread,
base::Unretained(this), std::move(task), future);
if (!thread_.task_runner()->PostTask(from_here, std::move(closure))) {
LOG(ERROR) << "Failed to post task";
return -EIO;
}
future->Wait();
return 0;
}
scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
return thread_.task_runner();
}
private:
template <typename T>
void ProcessSyncTaskOnThread(base::OnceCallback<T()> task,
scoped_refptr<cros::Future<T>> future) {
VLOGF_ENTER();
future->Set(std::move(task).Run());
}
template <typename T>
void ProcessASyncTaskOnThread(base::OnceCallback<T()> task) {
VLOGF_ENTER();
std::move(task).Run();
}
void ProcessClosureSyncTaskOnThread(
base::OnceClosure task, scoped_refptr<cros::Future<void>> future) {
VLOGF_ENTER();
std::move(task).Run();
future->Set();
}
base::Thread thread_;
};
} // namespace cros
#endif // CAMERA_INCLUDE_CROS_CAMERA_CAMERA_THREAD_H_