feat(frontends/lean/server): use separate thread for processing requests in server mode, interrupt whole parser when on interruption (when collecting information)
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
56a81eda6e
commit
8d4e27461c
4 changed files with 77 additions and 40 deletions
|
@ -220,7 +220,7 @@ void parser::protected_call(std::function<void()> && f, std::function<void()> &&
|
||||||
if (m_verbose)
|
if (m_verbose)
|
||||||
regular_stream() << "!!!Interrupted!!!" << endl;
|
regular_stream() << "!!!Interrupted!!!" << endl;
|
||||||
sync();
|
sync();
|
||||||
if (m_use_exceptions)
|
if (m_use_exceptions || m_info_manager)
|
||||||
throw;
|
throw;
|
||||||
} catch (script_exception & ex) {
|
} catch (script_exception & ex) {
|
||||||
reset_interrupt();
|
reset_interrupt();
|
||||||
|
|
|
@ -96,7 +96,7 @@ class parser {
|
||||||
// cache support
|
// cache support
|
||||||
definition_cache * m_cache;
|
definition_cache * m_cache;
|
||||||
// index support
|
// index support
|
||||||
declaration_index * m_index;
|
declaration_index * m_index;
|
||||||
|
|
||||||
void display_warning_pos(unsigned line, unsigned pos);
|
void display_warning_pos(unsigned line, unsigned pos);
|
||||||
void display_warning_pos(pos_info p);
|
void display_warning_pos(pos_info p);
|
||||||
|
|
|
@ -11,14 +11,12 @@ Author: Leonardo de Moura
|
||||||
#include "frontends/lean/parser.h"
|
#include "frontends/lean/parser.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
server::file::file(std::string const & fname):m_fname(fname), m_from(0) {}
|
server::file::file(std::string const & fname):m_fname(fname) {}
|
||||||
|
|
||||||
void server::file::replace_line(unsigned linenum, std::string const & new_line) {
|
void server::file::replace_line(unsigned linenum, std::string const & new_line) {
|
||||||
while (linenum >= m_lines.size())
|
while (linenum >= m_lines.size())
|
||||||
m_lines.push_back("");
|
m_lines.push_back("");
|
||||||
m_lines[linenum] = new_line;
|
m_lines[linenum] = new_line;
|
||||||
if (linenum < m_from)
|
|
||||||
m_from = linenum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::file::insert_line(unsigned linenum, std::string const & new_line) {
|
void server::file::insert_line(unsigned linenum, std::string const & new_line) {
|
||||||
|
@ -32,8 +30,6 @@ void server::file::insert_line(unsigned linenum, std::string const & new_line) {
|
||||||
m_lines[i] = m_lines[i-1];
|
m_lines[i] = m_lines[i-1];
|
||||||
}
|
}
|
||||||
m_lines[linenum] = new_line;
|
m_lines[linenum] = new_line;
|
||||||
if (linenum < m_from)
|
|
||||||
m_from = linenum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::file::remove_line(unsigned linenum) {
|
void server::file::remove_line(unsigned linenum) {
|
||||||
|
@ -43,8 +39,6 @@ void server::file::remove_line(unsigned linenum) {
|
||||||
for (unsigned i = linenum; i < m_lines.size()-1; i++)
|
for (unsigned i = linenum; i < m_lines.size()-1; i++)
|
||||||
m_lines[i] = m_lines[i+1];
|
m_lines[i] = m_lines[i+1];
|
||||||
m_lines.pop_back();
|
m_lines.pop_back();
|
||||||
if (linenum < m_from)
|
|
||||||
m_from = linenum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,6 +68,25 @@ unsigned server::file::find(unsigned linenum) {
|
||||||
server::server(environment const & env, io_state const & ios, unsigned num_threads):
|
server::server(environment const & env, io_state const & ios, unsigned num_threads):
|
||||||
m_env(env), m_ios(ios), m_out(ios.get_regular_channel().get_stream()),
|
m_env(env), m_ios(ios), m_out(ios.get_regular_channel().get_stream()),
|
||||||
m_num_threads(num_threads), m_empty_snapshot(m_env, m_ios.get_options()) {
|
m_num_threads(num_threads), m_empty_snapshot(m_env, m_ios.get_options()) {
|
||||||
|
m_thread_busy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
server::~server() {
|
||||||
|
reset_thread();
|
||||||
|
}
|
||||||
|
|
||||||
|
void server::interrupt_thread() {
|
||||||
|
if (m_thread_ptr)
|
||||||
|
m_thread_ptr->request_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void server::reset_thread() {
|
||||||
|
if (m_thread_ptr) {
|
||||||
|
m_thread_ptr->request_interrupt();
|
||||||
|
m_thread_ptr->join();
|
||||||
|
m_thread_ptr.reset(nullptr);
|
||||||
|
}
|
||||||
|
m_thread_busy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string g_load("LOAD");
|
static std::string g_load("LOAD");
|
||||||
|
@ -118,6 +131,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void server::process_from(unsigned linenum) {
|
void server::process_from(unsigned linenum) {
|
||||||
|
reset_thread();
|
||||||
unsigned i = m_file->find(linenum);
|
unsigned i = m_file->find(linenum);
|
||||||
m_file->m_snapshots.resize(i);
|
m_file->m_snapshots.resize(i);
|
||||||
snapshot & s = i == 0 ? m_empty_snapshot : m_file->m_snapshots[i-1];
|
snapshot & s = i == 0 ? m_empty_snapshot : m_file->m_snapshots[i-1];
|
||||||
|
@ -128,53 +142,48 @@ void server::process_from(unsigned linenum) {
|
||||||
block += m_file->m_lines[j];
|
block += m_file->m_lines[j];
|
||||||
block += '\n';
|
block += '\n';
|
||||||
}
|
}
|
||||||
std::istringstream strm(block);
|
|
||||||
scoped_updt_options updt(m_ios, s.m_options);
|
|
||||||
parser p(s.m_env, m_ios, strm, m_file->m_fname.c_str(), false, 1, s.m_lds, s.m_eds, s.m_line,
|
|
||||||
&m_file->m_snapshots, &m_file->m_info);
|
|
||||||
// p.set_cache(&m_cache);
|
// p.set_cache(&m_cache);
|
||||||
p();
|
m_thread_busy = true;
|
||||||
}
|
m_thread_ptr.reset(new interruptible_thread([=]() {
|
||||||
|
try {
|
||||||
void server::update() {
|
snapshot & s = i == 0 ? m_empty_snapshot : m_file->m_snapshots[i-1];
|
||||||
if (m_file->m_from == m_file->m_lines.size())
|
std::istringstream strm(block);
|
||||||
return;
|
scoped_updt_options updt(m_ios, s.m_options);
|
||||||
process_from(m_file->m_from);
|
parser p(s.m_env, m_ios, strm, m_file->m_fname.c_str(), false, 1, s.m_lds, s.m_eds, s.m_line,
|
||||||
m_file->m_from = m_file->m_lines.size();
|
&m_file->m_snapshots, &m_file->m_info);
|
||||||
|
p();
|
||||||
|
m_thread_busy = false;
|
||||||
|
std::cout << "DONE\n";
|
||||||
|
} catch (exception& ex) {}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::load_file(std::string const & fname) {
|
void server::load_file(std::string const & fname) {
|
||||||
|
interrupt_thread();
|
||||||
std::ifstream in(fname);
|
std::ifstream in(fname);
|
||||||
if (in.bad() || in.fail()) {
|
if (in.bad() || in.fail()) {
|
||||||
m_out << "-- ERROR failed to open file '" << fname << "'" << std::endl;
|
m_out << "-- ERROR failed to open file '" << fname << "'" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
reset_thread();
|
||||||
m_file.reset(new file(fname));
|
m_file.reset(new file(fname));
|
||||||
m_file_map.insert(mk_pair(fname, m_file));
|
m_file_map.insert(mk_pair(fname, m_file));
|
||||||
for (std::string line; std::getline(in, line);) {
|
for (std::string line; std::getline(in, line);) {
|
||||||
m_file->m_lines.push_back(line);
|
m_file->m_lines.push_back(line);
|
||||||
}
|
}
|
||||||
|
process_from(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::visit_file(std::string const & fname) {
|
void server::visit_file(std::string const & fname) {
|
||||||
|
interrupt_thread();
|
||||||
auto it = m_file_map.find(fname);
|
auto it = m_file_map.find(fname);
|
||||||
if (it == m_file_map.end())
|
if (it == m_file_map.end()) {
|
||||||
load_file(fname);
|
load_file(fname);
|
||||||
else
|
} else {
|
||||||
|
reset_thread();
|
||||||
m_file = it->second;
|
m_file = it->second;
|
||||||
}
|
process_from(0);
|
||||||
|
}
|
||||||
void server::show_info(unsigned linenum) {
|
|
||||||
check_file();
|
|
||||||
update();
|
|
||||||
unsigned i = m_file->find(linenum);
|
|
||||||
environment const & env = i == 0 ? m_env : m_file->m_snapshots[i-1].m_env;
|
|
||||||
options const & o = i == 0 ? m_ios.get_options() : m_file->m_snapshots[i-1].m_options;
|
|
||||||
scoped_updt_options updt(m_ios, o);
|
|
||||||
io_state_stream out(env, m_ios);
|
|
||||||
out << "-- BEGININFO" << endl;
|
|
||||||
m_file->m_info.display(out, linenum);
|
|
||||||
out << "-- ENDINFO" << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::read_line(std::istream & in, std::string & line) {
|
void server::read_line(std::istream & in, std::string & line) {
|
||||||
|
@ -198,18 +207,24 @@ void server::check_file() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::replace_line(unsigned linenum, std::string const & new_line) {
|
void server::replace_line(unsigned linenum, std::string const & new_line) {
|
||||||
|
interrupt_thread();
|
||||||
check_file();
|
check_file();
|
||||||
m_file->replace_line(linenum, new_line);
|
m_file->replace_line(linenum, new_line);
|
||||||
|
process_from(linenum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::insert_line(unsigned linenum, std::string const & new_line) {
|
void server::insert_line(unsigned linenum, std::string const & new_line) {
|
||||||
|
interrupt_thread();
|
||||||
check_file();
|
check_file();
|
||||||
m_file->insert_line(linenum, new_line);
|
m_file->insert_line(linenum, new_line);
|
||||||
|
process_from(linenum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::remove_line(unsigned linenum) {
|
void server::remove_line(unsigned linenum) {
|
||||||
|
interrupt_thread();
|
||||||
check_file();
|
check_file();
|
||||||
m_file->remove_line(linenum);
|
m_file->remove_line(linenum);
|
||||||
|
process_from(linenum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void server::check_line(unsigned linenum, std::string const & line) {
|
void server::check_line(unsigned linenum, std::string const & line) {
|
||||||
|
@ -238,9 +253,27 @@ void server::set_option(std::string const & line) {
|
||||||
m_out << "-- ENDSET" << std::endl;
|
m_out << "-- ENDSET" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void server::show_info(unsigned linenum) {
|
||||||
|
if (m_thread_busy) {
|
||||||
|
m_out << "-- BEGININFO\n-- NAY\n-- ENDINFO" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
check_file();
|
||||||
|
unsigned i = m_file->find(linenum);
|
||||||
|
environment const & env = i == 0 ? m_env : m_file->m_snapshots[i-1].m_env;
|
||||||
|
options const & o = i == 0 ? m_ios.get_options() : m_file->m_snapshots[i-1].m_options;
|
||||||
|
scoped_updt_options updt(m_ios, o);
|
||||||
|
io_state_stream out(env, m_ios);
|
||||||
|
out << "-- BEGININFO" << endl;
|
||||||
|
m_file->m_info.display(out, linenum);
|
||||||
|
out << "-- ENDINFO" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void server::eval(std::string const & line) {
|
void server::eval(std::string const & line) {
|
||||||
if (m_file)
|
if (m_thread_busy) {
|
||||||
update();
|
m_out << "-- BEGINEVAL\n-- NAY\n-- ENDEVAL" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
snapshot & s = !m_file || m_file->m_snapshots.empty() ? m_empty_snapshot : m_file->m_snapshots.back();
|
snapshot & s = !m_file || m_file->m_snapshots.empty() ? m_empty_snapshot : m_file->m_snapshots.back();
|
||||||
std::istringstream strm(line);
|
std::istringstream strm(line);
|
||||||
scoped_updt_options updt(m_ios, s.m_options);
|
scoped_updt_options updt(m_ios, s.m_options);
|
||||||
|
|
|
@ -8,6 +8,7 @@ Author: Leonardo de Moura
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include "util/interrupt.h"
|
||||||
#include "library/definition_cache.h"
|
#include "library/definition_cache.h"
|
||||||
#include "frontends/lean/parser.h"
|
#include "frontends/lean/parser.h"
|
||||||
#include "frontends/lean/info_manager.h"
|
#include "frontends/lean/info_manager.h"
|
||||||
|
@ -23,7 +24,6 @@ class server {
|
||||||
std::vector<std::string> m_lines;
|
std::vector<std::string> m_lines;
|
||||||
snapshot_vector m_snapshots;
|
snapshot_vector m_snapshots;
|
||||||
info_manager m_info;
|
info_manager m_info;
|
||||||
unsigned m_from; // mark the first modified line that was not processed yet.
|
|
||||||
|
|
||||||
file(std::string const & fname);
|
file(std::string const & fname);
|
||||||
unsigned find(unsigned linenum);
|
unsigned find(unsigned linenum);
|
||||||
|
@ -41,6 +41,8 @@ class server {
|
||||||
unsigned m_num_threads;
|
unsigned m_num_threads;
|
||||||
snapshot m_empty_snapshot;
|
snapshot m_empty_snapshot;
|
||||||
definition_cache m_cache;
|
definition_cache m_cache;
|
||||||
|
atomic<bool> m_thread_busy;
|
||||||
|
std::unique_ptr<interruptible_thread> m_thread_ptr;
|
||||||
|
|
||||||
void load_file(std::string const & fname);
|
void load_file(std::string const & fname);
|
||||||
void visit_file(std::string const & fname);
|
void visit_file(std::string const & fname);
|
||||||
|
@ -54,12 +56,14 @@ class server {
|
||||||
void set_option(std::string const & line);
|
void set_option(std::string const & line);
|
||||||
void eval(std::string const & line);
|
void eval(std::string const & line);
|
||||||
unsigned find(unsigned linenum);
|
unsigned find(unsigned linenum);
|
||||||
void update();
|
|
||||||
void read_line(std::istream & in, std::string & line);
|
void read_line(std::istream & in, std::string & line);
|
||||||
|
void reset_thread();
|
||||||
|
void interrupt_thread();
|
||||||
unsigned get_linenum(std::string const & line, std::string const & cmd);
|
unsigned get_linenum(std::string const & line, std::string const & cmd);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
server(environment const & env, io_state const & ios, unsigned num_threads = 1);
|
server(environment const & env, io_state const & ios, unsigned num_threads = 1);
|
||||||
|
~server();
|
||||||
bool operator()(std::istream & in);
|
bool operator()(std::istream & in);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue