lean4-htt/src/util/task.cpp
2017-03-23 09:16:49 +01:00

94 lines
2.3 KiB
C++

/*
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Gabriel Ebner
*/
#include "util/task.h"
namespace lean {
void gtask_cell::cancel(std::shared_ptr<cancellable> const & self) {
if (auto self_task = std::dynamic_pointer_cast<gtask_cell>(self)) {
taskq().fail_and_dispose(self_task);
}
}
std::exception_ptr gtask_cell::peek_exception() const {
if (m_state.load() == task_state::Failed) {
return m_exception;
} else {
return {};
}
}
void task_queue::wait_for_success(gtask const & t) {
while (true) {
switch (t->m_state.load()) {
case task_state::Success:
return; // OK
case task_state::Failed:
std::rethrow_exception(t->m_exception);
default:
wait_for_finish(t);
}
}
}
void task_queue::execute(gtask const & t) {
lean_always_assert(t);
lean_always_assert(t->m_state.load() == task_state::Running);
lean_always_assert(t->m_data);
lean_always_assert(t->m_data->m_imp);
try {
bool did_wait = true;
while (did_wait) {
did_wait = false;
buffer<gtask> deps;
t->m_data->m_imp->get_dependencies(deps);
for (auto & dep : deps) {
if (dep && !dep->peek_is_finished()) {
did_wait = true;
wait_for_finish(dep);
}
}
}
t->execute();
t->m_state = task_state::Success;
} catch (...) {
t->m_exception = std::current_exception();
t->m_state = task_state::Failed;
}
}
void task_queue::fail(gtask const & t, std::exception_ptr const & ex) {
lean_always_assert(t->m_state.load() < task_state::Running);
t->m_exception = ex;
t->m_state = task_state::Failed;
}
void task_queue::fail(gtask const & t, gtask const & failed) {
lean_always_assert(failed->m_state.load() == task_state::Failed);
fail(t, failed->m_exception);
}
void task_queue::submit(gtask const & t, unsigned) {
return submit(t);
}
static task_queue * g_taskq = nullptr;
void set_task_queue(task_queue * q) {
if (g_taskq) throw exception("cannot set task queue twice");
g_taskq = q;
}
task_queue & taskq() {
return *g_taskq;
}
}