Files
mob/src/tasks/task.cpp
T

332 lines
4.9 KiB
C++
Raw Normal View History

2020-04-29 22:10:55 -04:00
#include "pch.h"
#include "task.h"
2020-05-02 04:03:20 -04:00
#include "../conf.h"
#include "../op.h"
2020-05-03 03:46:58 -04:00
#include "../tools/tools.h"
2020-04-29 22:10:55 -04:00
2020-05-02 03:12:34 -04:00
namespace mob
2020-04-29 22:10:55 -04:00
{
class interrupted {};
std::vector<std::unique_ptr<task>> g_tasks;
std::mutex task::interrupt_mutex_;
void add_task(std::unique_ptr<task> t)
{
g_tasks.push_back(std::move(t));
}
2020-05-06 14:07:45 -04:00
void list_tasks(bool err)
{
for (auto&& t : g_tasks)
{
if (err)
std::cerr << " - " << join(t->names(), ", ") << "\n";
else
std::cout << " - " << join(t->names(), ", ") << "\n";
}
}
task* find_task(const std::string& name)
2020-04-29 22:10:55 -04:00
{
for (auto&& t : g_tasks)
{
2020-05-03 03:32:40 -04:00
for (auto&& n : t->names())
2020-04-29 22:10:55 -04:00
{
2020-05-03 03:32:40 -04:00
if (n == name)
return t.get();
2020-04-29 22:10:55 -04:00
}
}
2020-05-06 14:07:45 -04:00
std::cout << "task " << name << " not found\n";
std::cout << "valid tasks:\n";
list_tasks(true);
2020-04-29 22:10:55 -04:00
throw bailed("");
2020-04-29 22:10:55 -04:00
}
2020-05-06 13:39:47 -04:00
void run_tasks(const std::set<task*> tasks)
{
for (auto* t : tasks)
t->fetch();
for (auto* t : tasks)
{
t->join();
t->build_and_install();
t->join();
}
}
2020-05-06 13:39:47 -04:00
void gather_super_tasks(std::set<task*>& tasks)
{
for (auto& t : g_tasks)
{
if (t->is_super())
tasks.insert(t.get());
}
}
void run_task(const std::string& name)
{
run_tasks({find_task(name)});
}
void run_tasks(const std::vector<std::string>& names)
2020-05-06 03:39:45 -04:00
{
if (names.empty())
return;
2020-05-06 03:39:45 -04:00
if (names.size() == 1)
gcx().debug(context::generic, "specified task: " + names[0]);
else
gcx().debug(context::generic, "specified tasks: " + join(names, " "));
2020-05-06 13:39:47 -04:00
std::set<task*> tasks;
for (auto&& name : names)
2020-05-06 13:39:47 -04:00
{
if (name == "super")
gather_super_tasks(tasks);
else
tasks.insert(find_task(name));
}
2020-05-06 03:39:45 -04:00
run_tasks(tasks);
2020-05-06 03:39:45 -04:00
}
void run_all_tasks()
2020-04-29 22:10:55 -04:00
{
2020-05-06 13:39:47 -04:00
std::set<task*> tasks;
2020-04-29 22:10:55 -04:00
for (auto&& t : g_tasks)
2020-05-06 13:39:47 -04:00
tasks.insert(t.get());
2020-05-06 03:39:45 -04:00
run_tasks(tasks);
2020-04-29 22:10:55 -04:00
}
2020-05-03 03:32:40 -04:00
task::task(std::vector<std::string> names)
2020-05-04 05:38:23 -04:00
: names_(std::move(names)), interrupted_(false)
2020-05-03 03:32:40 -04:00
{
2020-05-04 05:38:23 -04:00
contexts_.push_back(std::make_unique<thread_context>(
std::this_thread::get_id(), context(name())));
2020-05-03 03:32:40 -04:00
}
2020-04-29 22:10:55 -04:00
task::~task()
{
try
{
join();
}
catch(bailed)
{
// ignore
}
}
2020-05-06 13:39:47 -04:00
bool task::is_super() const
{
return false;
}
2020-05-04 05:38:23 -04:00
const context& task::cx() const
{
static const context bad("?");
{
std::scoped_lock lock(contexts_mutex_);
for (auto& td : contexts_)
{
if (td->tid == std::this_thread::get_id())
return td->cx;
}
}
return bad;
}
2020-05-06 12:29:38 -04:00
void task::add_name(std::string s)
{
names_.push_back(s);
}
2020-04-29 22:10:55 -04:00
void task::interrupt_all()
{
std::scoped_lock lock(interrupt_mutex_);
for (auto&& t : g_tasks)
t->interrupt();
}
const std::string& task::name() const
{
2020-05-03 03:32:40 -04:00
return names_[0];
}
const std::vector<std::string>& task::names() const
{
return names_;
2020-04-29 22:10:55 -04:00
}
2020-05-04 05:38:23 -04:00
void task::threaded_run(std::string thread_name, std::function<void ()> f)
{
try
{
{
std::scoped_lock lock(contexts_mutex_);
contexts_.push_back(std::make_unique<thread_context>(
std::this_thread::get_id(), context(thread_name)));
}
guard g([&]
{
std::scoped_lock lock(contexts_mutex_);
for (auto itor=contexts_.begin(); itor!=contexts_.end(); ++itor)
{
if ((*itor)->tid == std::this_thread::get_id())
{
contexts_.erase(itor);
break;
}
}
});
f();
}
catch(bailed e)
{
error(name() + " bailed out, interrupting all tasks");
interrupt_all();
}
catch(interrupted)
{
return;
}
catch(std::exception& e)
{
error(name() + " uncaught exception: " + e.what());
interrupt_all();
}
}
2020-04-29 22:10:55 -04:00
void task::run()
{
2020-05-04 05:38:23 -04:00
cx().info(context::generic, "running task");
2020-04-29 22:10:55 -04:00
fetch();
join();
2020-05-02 04:03:20 -04:00
build_and_install();
join();
2020-05-04 03:02:33 -04:00
cx().info(context::generic, "task completed");
2020-04-29 22:10:55 -04:00
}
void task::interrupt()
{
2020-05-04 05:38:23 -04:00
std::scoped_lock lock(tools_mutex_);
2020-04-29 22:10:55 -04:00
interrupted_ = true;
2020-05-04 05:38:23 -04:00
for (auto* t : tools_)
t->interrupt();
2020-04-29 22:10:55 -04:00
}
void task::join()
{
if (thread_.joinable())
thread_.join();
}
void task::fetch()
{
thread_ = std::thread([&]
{
threaded_run(name(), [&]
{
if (conf::rebuild())
clean_for_rebuild();
2020-04-29 22:10:55 -04:00
check_interrupted();
cx().info(context::generic, "fetching");
do_fetch();
check_interrupted();
2020-05-06 05:22:42 -04:00
if (!get_source_path().empty())
{
2020-05-06 07:43:15 -04:00
cx().debug(context::generic, "patching");
2020-05-06 05:22:42 -04:00
run_tool(patcher()
.task(name())
.root(get_source_path()));
}
check_interrupted();
});
});
2020-04-29 22:10:55 -04:00
}
void task::build_and_install()
{
thread_ = std::thread([&]
{
threaded_run(name(), [&]
{
check_interrupted();
cx().info(context::generic, "build and install");
do_build_and_install();
check_interrupted();
});
});
2020-04-29 22:10:55 -04:00
}
void task::clean_for_rebuild()
2020-05-02 04:03:20 -04:00
{
cx().info(context::rebuild, "cleaning");
do_clean_for_rebuild();
2020-05-02 04:03:20 -04:00
}
2020-04-29 22:10:55 -04:00
void task::check_interrupted()
{
if (interrupted_)
throw interrupted();
}
2020-05-04 05:38:23 -04:00
void task::run_tool_impl(tool* t)
2020-05-03 03:32:40 -04:00
{
2020-05-04 05:38:23 -04:00
{
std::scoped_lock lock(tools_mutex_);
tools_.push_back(t);
}
guard g([&]
{
std::scoped_lock lock(tools_mutex_);
for (auto itor=tools_.begin(); itor!=tools_.end(); ++itor)
{
if (*itor == t)
{
tools_.erase(itor);
break;
}
}
});
cx().debug(context::generic, "running tool " + t->name());
context cxcopy(cx());
2020-05-03 05:42:56 -04:00
2020-05-03 03:32:40 -04:00
check_interrupted();
2020-05-04 05:38:23 -04:00
t->run(cxcopy);
2020-05-03 03:32:40 -04:00
check_interrupted();
}
2020-04-29 22:10:55 -04:00
} // namespace