blob: ef516cdcbf580fbfabc7bfbd79f5af2c2a3de5c9 [file] [log] [blame] [edit]
#ifndef THIRD_PARTY_EIGEN3_GOOGLE_THREADS_ENV_H_
#define THIRD_PARTY_EIGEN3_GOOGLE_THREADS_ENV_H_
#include <functional>
#include <string>
#include <utility>
#include "thread/fiber/fiber.h"
#include "thread/thread.h"
#include "thread/thread_options.h"
namespace Eigen {
inline std::string GetGoogleNamePrefix() { return "GoogleEigen_"; }
// Implements the `Environment` interface needed by Eigen's `ThreadPoolTempl`
// class. See Eigen's `ThreadEnvironment.h` for an implementation that uses the
// banned `std::thread` library.
struct GoogleEnvironment {
struct Task {
std::function<void()> f;
};
struct EnvThread {};
virtual ~GoogleEnvironment() = default;
virtual EnvThread* CreateThread(std::function<void()> f) = 0;
virtual Task CreateTask(std::function<void()> f) = 0;
virtual void ExecuteTask(const Task& task) = 0;
};
// Uses Google Threads (go/c++-concurrency#threads_fibers) to handle thread
// management.
struct GoogleThreadEnvironment : public GoogleEnvironment {
// Constructor must start the thread, while destructor must join it.
struct EnvThread : public GoogleEnvironment::EnvThread {
EnvThread(std::function<void()> f) : func_thread_(std::move(f)) {
func_thread_.Start();
};
~EnvThread() { func_thread_.Join(); };
void OnCancel() {};
private:
// Wraps a function in a thread and calls it when the thread starts.
// Needed to conform to Eigen's `EnvThread` interface.
class FuncThread : public ::Thread {
public:
static ::thread::Options options() {
::thread::Options options;
options.set_joinable(true);
return options;
}
FuncThread(std::function<void()> f)
: ::Thread(options(), GetGoogleNamePrefix()), f_(std::move(f)) {};
~FuncThread() override = default;
void Run() override { f_(); };
private:
std::function<void()> f_;
};
// Managed by `EnvThread` internally.
FuncThread func_thread_;
};
EnvThread* CreateThread(std::function<void()> f) {
return new EnvThread(std::move(f));
}
Task CreateTask(std::function<void()> f) { return Task{std::move(f)}; }
void ExecuteTask(const Task& task) { task.f(); }
};
// Uses Google Fibers (go/fibers) to handle thread management.
struct GoogleFiberEnvironment : public GoogleEnvironment {
// Constructor must start the thread, while destructor must join it.
struct EnvThread : public GoogleEnvironment::EnvThread {
EnvThread(std::function<void()> f) : fiber_(std::move(f)) {};
~EnvThread() { fiber_.Join(); };
void OnCancel() {};
private:
::thread::Fiber fiber_;
};
EnvThread* CreateThread(std::function<void()> f) {
return new EnvThread(std::move(f));
}
Task CreateTask(std::function<void()> f) { return Task{std::move(f)}; }
void ExecuteTask(const Task& task) { task.f(); }
};
} // namespace Eigen
#endif // THIRD_PARTY_EIGEN3_GOOGLE_THREADS_ENV_H_