Browse Source

Merge branch 'improve_exception_safety' of https://github.com/milleniumbug/jucipp

merge-requests/365/head
eidheim 10 years ago
parent
commit
3175ac2d90
  1. 61
      src/debug_clang.cc
  2. 32
      src/directories.cc
  3. 10
      src/dispatcher.cc
  4. 6
      src/project.cc
  5. 37
      src/source_clang.cc
  6. 61
      src/terminal.cc

61
src/debug_clang.cc

@ -110,7 +110,7 @@ void Debug::Clang::start(const std::string &command, const boost::filesystem::pa
debug_thread=std::thread([this, callback, status_callback, stop_callback]() { debug_thread=std::thread([this, callback, status_callback, stop_callback]() {
lldb::SBEvent event; lldb::SBEvent event;
while(true) { while(true) {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(listener->GetNextEvent(event)) { if(listener->GetNextEvent(event)) {
if((event.GetType() & lldb::SBProcess::eBroadcastBitStateChanged)>0) { if((event.GetType() & lldb::SBProcess::eBroadcastBitStateChanged)>0) {
auto state=process->GetStateFromEvent(event); auto state=process->GetStateFromEvent(event);
@ -178,7 +178,6 @@ void Debug::Clang::start(const std::string &command, const boost::filesystem::pa
stop_callback("", 0, 0); stop_callback("", 0, 0);
process.reset(); process.reset();
this->state=lldb::StateType::eStateInvalid; this->state=lldb::StateType::eStateInvalid;
event_mutex.unlock();
return; return;
} }
else if(state==lldb::StateType::eStateCrashed) { else if(state==lldb::StateType::eStateCrashed) {
@ -190,7 +189,6 @@ void Debug::Clang::start(const std::string &command, const boost::filesystem::pa
stop_callback("", 0, 0); stop_callback("", 0, 0);
process.reset(); process.reset();
this->state=lldb::StateType::eStateInvalid; this->state=lldb::StateType::eStateInvalid;
event_mutex.unlock();
return; return;
} }
} }
@ -208,79 +206,72 @@ void Debug::Clang::start(const std::string &command, const boost::filesystem::pa
Terminal::get().async_print(std::string(buffer, n), true); Terminal::get().async_print(std::string(buffer, n), true);
} }
} }
event_mutex.unlock(); lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(200)); std::this_thread::sleep_for(std::chrono::milliseconds(200));
} }
}); });
} }
void Debug::Clang::continue_debug() { void Debug::Clang::continue_debug() {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) if(state==lldb::StateType::eStateStopped)
process->Continue(); process->Continue();
event_mutex.unlock();
} }
void Debug::Clang::stop() { void Debug::Clang::stop() {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateRunning) { if(state==lldb::StateType::eStateRunning) {
auto error=process->Stop(); auto error=process->Stop();
if(error.Fail()) if(error.Fail())
Terminal::get().async_print(std::string("Error (debug): ")+error.GetCString()+'\n', true); Terminal::get().async_print(std::string("Error (debug): ")+error.GetCString()+'\n', true);
} }
event_mutex.unlock();
} }
void Debug::Clang::kill() { void Debug::Clang::kill() {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(process) { if(process) {
auto error=process->Kill(); auto error=process->Kill();
if(error.Fail()) if(error.Fail())
Terminal::get().async_print(std::string("Error (debug): ")+error.GetCString()+'\n', true); Terminal::get().async_print(std::string("Error (debug): ")+error.GetCString()+'\n', true);
} }
event_mutex.unlock();
} }
void Debug::Clang::step_over() { void Debug::Clang::step_over() {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
process->GetSelectedThread().StepOver(); process->GetSelectedThread().StepOver();
} }
event_mutex.unlock();
} }
void Debug::Clang::step_into() { void Debug::Clang::step_into() {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
process->GetSelectedThread().StepInto(); process->GetSelectedThread().StepInto();
} }
event_mutex.unlock();
} }
void Debug::Clang::step_out() { void Debug::Clang::step_out() {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
process->GetSelectedThread().StepOut(); process->GetSelectedThread().StepOut();
} }
event_mutex.unlock();
} }
std::pair<std::string, std::string> Debug::Clang::run_command(const std::string &command) { std::pair<std::string, std::string> Debug::Clang::run_command(const std::string &command) {
std::pair<std::string, std::string> command_return; std::pair<std::string, std::string> command_return;
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped || state==lldb::StateType::eStateRunning) { if(state==lldb::StateType::eStateStopped || state==lldb::StateType::eStateRunning) {
lldb::SBCommandReturnObject command_return_object; lldb::SBCommandReturnObject command_return_object;
debugger->GetCommandInterpreter().HandleCommand(command.c_str(), command_return_object, true); debugger->GetCommandInterpreter().HandleCommand(command.c_str(), command_return_object, true);
command_return.first=command_return_object.GetOutput(); command_return.first=command_return_object.GetOutput();
command_return.second=command_return_object.GetError(); command_return.second=command_return_object.GetError();
} }
event_mutex.unlock();
return command_return; return command_return;
} }
std::vector<Debug::Clang::Frame> Debug::Clang::get_backtrace() { std::vector<Debug::Clang::Frame> Debug::Clang::get_backtrace() {
std::vector<Frame> backtrace; std::vector<Frame> backtrace;
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
auto thread=process->GetSelectedThread(); auto thread=process->GetSelectedThread();
for(uint32_t c_f=0;c_f<thread.GetNumFrames();c_f++) { for(uint32_t c_f=0;c_f<thread.GetNumFrames();c_f++) {
@ -311,13 +302,12 @@ std::vector<Debug::Clang::Frame> Debug::Clang::get_backtrace() {
backtrace.emplace_back(backtrace_frame); backtrace.emplace_back(backtrace_frame);
} }
} }
event_mutex.unlock();
return backtrace; return backtrace;
} }
std::vector<Debug::Clang::Variable> Debug::Clang::get_variables() { std::vector<Debug::Clang::Variable> Debug::Clang::get_variables() {
std::vector<Debug::Clang::Variable> variables; std::vector<Debug::Clang::Variable> variables;
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
for(uint32_t c_t=0;c_t<process->GetNumThreads();c_t++) { for(uint32_t c_t=0;c_t<process->GetNumThreads();c_t++) {
auto thread=process->GetThreadAtIndex(c_t); auto thread=process->GetThreadAtIndex(c_t);
@ -355,18 +345,16 @@ std::vector<Debug::Clang::Variable> Debug::Clang::get_variables() {
} }
} }
} }
event_mutex.unlock();
return variables; return variables;
} }
void Debug::Clang::select_frame(uint32_t frame_index, uint32_t thread_index_id) { void Debug::Clang::select_frame(uint32_t frame_index, uint32_t thread_index_id) {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
if(thread_index_id!=0) if(thread_index_id!=0)
process->SetSelectedThreadByIndexID(thread_index_id); process->SetSelectedThreadByIndexID(thread_index_id);
process->GetSelectedThread().SetSelectedFrame(frame_index);; process->GetSelectedThread().SetSelectedFrame(frame_index);;
} }
event_mutex.unlock();
} }
void Debug::Clang::delete_debug() { void Debug::Clang::delete_debug() {
@ -377,7 +365,7 @@ void Debug::Clang::delete_debug() {
std::string Debug::Clang::get_value(const std::string &variable, const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) { std::string Debug::Clang::get_value(const std::string &variable, const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) {
std::string variable_value; std::string variable_value;
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
auto frame=process->GetSelectedThread().GetSelectedFrame(); auto frame=process->GetSelectedThread().GetSelectedFrame();
@ -413,13 +401,12 @@ std::string Debug::Clang::get_value(const std::string &variable, const boost::fi
} }
} }
} }
event_mutex.unlock();
return variable_value; return variable_value;
} }
std::string Debug::Clang::get_return_value(const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) { std::string Debug::Clang::get_return_value(const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) {
std::string return_value; std::string return_value;
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
auto thread=process->GetSelectedThread(); auto thread=process->GetSelectedThread();
auto thread_return_value=thread.GetStopReturnValue(); auto thread_return_value=thread.GetStopReturnValue();
@ -437,45 +424,40 @@ std::string Debug::Clang::get_return_value(const boost::filesystem::path &file_p
} }
} }
} }
event_mutex.unlock();
return return_value; return return_value;
} }
bool Debug::Clang::is_invalid() { bool Debug::Clang::is_invalid() {
bool invalid; bool invalid;
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
invalid=state==lldb::StateType::eStateInvalid; invalid=state==lldb::StateType::eStateInvalid;
event_mutex.unlock();
return invalid; return invalid;
} }
bool Debug::Clang::is_stopped() { bool Debug::Clang::is_stopped() {
bool stopped; bool stopped;
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
stopped=state==lldb::StateType::eStateStopped; stopped=state==lldb::StateType::eStateStopped;
event_mutex.unlock();
return stopped; return stopped;
} }
bool Debug::Clang::is_running() { bool Debug::Clang::is_running() {
bool running; bool running;
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
running=state==lldb::StateType::eStateRunning; running=state==lldb::StateType::eStateRunning;
event_mutex.unlock();
return running; return running;
} }
void Debug::Clang::add_breakpoint(const boost::filesystem::path &file_path, int line_nr) { void Debug::Clang::add_breakpoint(const boost::filesystem::path &file_path, int line_nr) {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::eStateStopped || state==lldb::eStateRunning) { if(state==lldb::eStateStopped || state==lldb::eStateRunning) {
if(!(process->GetTarget().BreakpointCreateByLocation(file_path.string().c_str(), line_nr)).IsValid()) if(!(process->GetTarget().BreakpointCreateByLocation(file_path.string().c_str(), line_nr)).IsValid())
Terminal::get().async_print("Error (debug): Could not create breakpoint at: "+file_path.string()+":"+std::to_string(line_nr)+'\n', true); Terminal::get().async_print("Error (debug): Could not create breakpoint at: "+file_path.string()+":"+std::to_string(line_nr)+'\n', true);
} }
event_mutex.unlock();
} }
void Debug::Clang::remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) { void Debug::Clang::remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::eStateStopped || state==lldb::eStateRunning) { if(state==lldb::eStateStopped || state==lldb::eStateRunning) {
auto target=process->GetTarget(); auto target=process->GetTarget();
for(int line_nr_try=line_nr;line_nr_try<line_count;line_nr_try++) { for(int line_nr_try=line_nr;line_nr_try<line_count;line_nr_try++) {
@ -490,7 +472,6 @@ void Debug::Clang::remove_breakpoint(const boost::filesystem::path &file_path, i
if(breakpoint_path==file_path) { if(breakpoint_path==file_path) {
if(!target.BreakpointDelete(breakpoint.GetID())) if(!target.BreakpointDelete(breakpoint.GetID()))
Terminal::get().async_print("Error (debug): Could not delete breakpoint at: "+file_path.string()+":"+std::to_string(line_nr)+'\n', true); Terminal::get().async_print("Error (debug): Could not delete breakpoint at: "+file_path.string()+":"+std::to_string(line_nr)+'\n', true);
event_mutex.unlock();
return; return;
} }
} }
@ -498,13 +479,11 @@ void Debug::Clang::remove_breakpoint(const boost::filesystem::path &file_path, i
} }
} }
} }
event_mutex.unlock();
} }
void Debug::Clang::write(const std::string &buffer) { void Debug::Clang::write(const std::string &buffer) {
event_mutex.lock(); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateRunning) { if(state==lldb::StateType::eStateRunning) {
process->PutSTDIN(buffer.c_str(), buffer.size()); process->PutSTDIN(buffer.c_str(), buffer.size());
} }
event_mutex.unlock();
} }

32
src/directories.cc

@ -147,14 +147,14 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
signal_test_expand_row().connect([this](const Gtk::TreeModel::iterator &iter, const Gtk::TreeModel::Path &path){ signal_test_expand_row().connect([this](const Gtk::TreeModel::iterator &iter, const Gtk::TreeModel::Path &path){
if(iter->children().begin()->get_value(column_record.path)=="") { if(iter->children().begin()->get_value(column_record.path)=="") {
update_mutex.lock(); std::unique_lock<std::mutex> lock(update_mutex);
add_path(iter->get_value(column_record.path), *iter); add_path(iter->get_value(column_record.path), *iter);
update_mutex.unlock();
} }
return false; return false;
}); });
signal_row_collapsed().connect([this](const Gtk::TreeModel::iterator &iter, const Gtk::TreeModel::Path &path){ signal_row_collapsed().connect([this](const Gtk::TreeModel::iterator &iter, const Gtk::TreeModel::Path &path){
update_mutex.lock(); {
std::unique_lock<std::mutex> lock(update_mutex);
auto directory_str=iter->get_value(column_record.path).string(); auto directory_str=iter->get_value(column_record.path).string();
for(auto it=last_write_times.begin();it!=last_write_times.end();) { for(auto it=last_write_times.begin();it!=last_write_times.end();) {
if(directory_str==it->first.substr(0, directory_str.size())) if(directory_str==it->first.substr(0, directory_str.size()))
@ -162,7 +162,7 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
else else
it++; it++;
} }
update_mutex.unlock(); }
auto children=iter->children(); auto children=iter->children();
if(children) { if(children) {
while(children) { while(children) {
@ -179,7 +179,7 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
update_thread=std::thread([this](){ update_thread=std::thread([this](){
while(!stop_update_thread) { while(!stop_update_thread) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for(std::chrono::milliseconds(1000));
update_mutex.lock(); std::unique_lock<std::mutex> lock(update_mutex);
for(auto it=last_write_times.begin();it!=last_write_times.end();) { for(auto it=last_write_times.begin();it!=last_write_times.end();) {
boost::system::error_code ec; boost::system::error_code ec;
auto last_write_time=boost::filesystem::last_write_time(it->first, ec); auto last_write_time=boost::filesystem::last_write_time(it->first, ec);
@ -188,11 +188,10 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
if(last_write_time!=now && it->second.second<last_write_time) { if(last_write_time!=now && it->second.second<last_write_time) {
auto path=std::make_shared<std::string>(it->first); auto path=std::make_shared<std::string>(it->first);
dispatcher.post([this, path, last_write_time] { dispatcher.post([this, path, last_write_time] {
update_mutex.lock(); std::unique_lock<std::mutex> lock(update_mutex);
auto it=last_write_times.find(*path); auto it=last_write_times.find(*path);
if(it!=last_write_times.end()) if(it!=last_write_times.end())
add_path(*path, it->second.first, last_write_time); add_path(*path, it->second.first, last_write_time);
update_mutex.unlock();
}); });
} }
it++; it++;
@ -200,7 +199,6 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
else else
it=last_write_times.erase(it); it=last_write_times.erase(it);
} }
update_mutex.unlock();
} }
}); });
@ -315,9 +313,10 @@ void Directories::open(const boost::filesystem::path &dir_path) {
return; return;
tree_store->clear(); tree_store->clear();
update_mutex.lock(); {
std::unique_lock<std::mutex> lock(update_mutex);
last_write_times.clear(); last_write_times.clear();
update_mutex.unlock(); }
//TODO: report that set_title does not handle '_' correctly? //TODO: report that set_title does not handle '_' correctly?
@ -329,9 +328,10 @@ void Directories::open(const boost::filesystem::path &dir_path) {
} }
get_column(0)->set_title(title); get_column(0)->set_title(title);
update_mutex.lock(); {
std::unique_lock<std::mutex> lock(update_mutex);
add_path(dir_path, Gtk::TreeModel::Row()); add_path(dir_path, Gtk::TreeModel::Row());
update_mutex.unlock(); }
path=dir_path; path=dir_path;
@ -340,11 +340,12 @@ void Directories::open(const boost::filesystem::path &dir_path) {
void Directories::update() { void Directories::update() {
JDEBUG("start"); JDEBUG("start");
update_mutex.lock(); {
std::unique_lock<std::mutex> lock(update_mutex);
for(auto &last_write_time: last_write_times) { for(auto &last_write_time: last_write_times) {
add_path(last_write_time.first, last_write_time.second.first); add_path(last_write_time.first, last_write_time.second.first);
} }
update_mutex.unlock(); }
JDEBUG("end"); JDEBUG("end");
} }
@ -371,9 +372,8 @@ void Directories::select(const boost::filesystem::path &select_path) {
for(auto &a_path: paths) { for(auto &a_path: paths) {
tree_store->foreach_iter([this, &a_path](const Gtk::TreeModel::iterator &iter){ tree_store->foreach_iter([this, &a_path](const Gtk::TreeModel::iterator &iter){
if(iter->get_value(column_record.path)==a_path) { if(iter->get_value(column_record.path)==a_path) {
update_mutex.lock(); std::unique_lock<std::mutex> lock(update_mutex);
add_path(a_path, *iter); add_path(a_path, *iter);
update_mutex.unlock();
return true; return true;
} }
return false; return false;

10
src/dispatcher.cc

@ -2,26 +2,24 @@
Dispatcher::Dispatcher() { Dispatcher::Dispatcher() {
connection=dispatcher.connect([this] { connection=dispatcher.connect([this] {
functions_mutex.lock(); std::unique_lock<std::mutex> lock(functions_mutex);
for(auto &function: functions) { for(auto &function: functions) {
function(); function();
} }
functions.clear(); functions.clear();
functions_mutex.unlock();
}); });
} }
Dispatcher::~Dispatcher() { Dispatcher::~Dispatcher() {
disconnect(); disconnect();
functions_mutex.lock(); std::unique_lock<std::mutex> lock(functions_mutex);
functions.clear(); functions.clear();
functions_mutex.unlock();
} }
void Dispatcher::post(std::function<void()> &&function) { void Dispatcher::post(std::function<void()> &&function) {
functions_mutex.lock(); std::unique_lock<std::mutex> lock(functions_mutex);
functions.emplace_back(function); functions.emplace_back(function);
functions_mutex.unlock(); lock.unlock();
dispatcher(); dispatcher();
} }

6
src/project.cc

@ -293,7 +293,7 @@ void Project::Clang::debug_start() {
if(exit_status!=EXIT_SUCCESS) if(exit_status!=EXIT_SUCCESS)
debugging=false; debugging=false;
else { else {
debug_start_mutex.lock(); std::unique_lock<std::mutex> lock(debug_start_mutex);
Debug::Clang::get().start(run_arguments, project_path, *breakpoints, [this, run_arguments](int exit_status){ Debug::Clang::get().start(run_arguments, project_path, *breakpoints, [this, run_arguments](int exit_status){
debugging=false; debugging=false;
Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n'); Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n');
@ -310,7 +310,6 @@ void Project::Clang::debug_start() {
debug_update_stop(); debug_update_stop();
}); });
}); });
debug_start_mutex.unlock();
} }
}); });
} }
@ -497,9 +496,8 @@ void Project::Clang::debug_write(const std::string &buffer) {
} }
void Project::Clang::debug_delete() { void Project::Clang::debug_delete() {
debug_start_mutex.lock(); std::unique_lock<std::mutex> lock(debug_start_mutex);
Debug::Clang::get().delete_debug(); Debug::Clang::get().delete_debug();
debug_start_mutex.unlock();
} }
#endif #endif

37
src/source_clang.cc

@ -106,28 +106,31 @@ void Source::ClangViewParse::parse_initialize() {
if(parse_state!=ParseState::PROCESSING) if(parse_state!=ParseState::PROCESSING)
break; break;
auto expected=ParseProcessState::STARTING; auto expected=ParseProcessState::STARTING;
std::unique_lock<std::mutex> parse_lock(parse_mutex, std::defer_lock);
if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::PREPROCESSING)) { if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::PREPROCESSING)) {
dispatcher.post([this] { dispatcher.post([this] {
auto expected=ParseProcessState::PREPROCESSING; auto expected=ParseProcessState::PREPROCESSING;
if(parse_mutex.try_lock()) { std::unique_lock<std::mutex> parse_lock(parse_mutex, std::defer_lock);
if(parse_lock.try_lock()) {
if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::PROCESSING)) if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::PROCESSING))
parse_thread_buffer=get_buffer()->get_text(); parse_thread_buffer=get_buffer()->get_text();
parse_mutex.unlock(); parse_lock.unlock();
} }
else else
parse_process_state.compare_exchange_strong(expected, ParseProcessState::STARTING); parse_process_state.compare_exchange_strong(expected, ParseProcessState::STARTING);
}); });
} }
else if (parse_process_state==ParseProcessState::PROCESSING && parse_mutex.try_lock()) { else if (parse_process_state==ParseProcessState::PROCESSING && parse_lock.try_lock()) {
auto status=clang_tu->ReparseTranslationUnit(parse_thread_buffer.raw()); auto status=clang_tu->ReparseTranslationUnit(parse_thread_buffer.raw());
parsing_in_progress->done("done"); parsing_in_progress->done("done");
if(status==0) { if(status==0) {
auto expected=ParseProcessState::PROCESSING; auto expected=ParseProcessState::PROCESSING;
if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::POSTPROCESSING)) { if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::POSTPROCESSING)) {
clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer.bytes()-1); clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer.bytes()-1);
parse_mutex.unlock(); parse_lock.unlock();
dispatcher.post([this] { dispatcher.post([this] {
if(parse_mutex.try_lock()) { std::unique_lock<std::mutex> parse_lock(parse_mutex, std::defer_lock);
if(parse_lock.try_lock()) {
auto expected=ParseProcessState::POSTPROCESSING; auto expected=ParseProcessState::POSTPROCESSING;
if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::IDLE)) { if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::IDLE)) {
update_syntax(); update_syntax();
@ -135,16 +138,16 @@ void Source::ClangViewParse::parse_initialize() {
parsed=true; parsed=true;
set_status(""); set_status("");
} }
parse_mutex.unlock(); parse_lock.unlock();
} }
}); });
} }
else else
parse_mutex.unlock(); parse_lock.unlock();
} }
else { else {
parse_state=ParseState::STOP; parse_state=ParseState::STOP;
parse_mutex.unlock(); parse_lock.unlock();
dispatcher.post([this] { dispatcher.post([this] {
Terminal::get().print("Error: failed to reparse "+this->file_path.string()+".\n", true); Terminal::get().print("Error: failed to reparse "+this->file_path.string()+".\n", true);
set_status(""); set_status("");
@ -623,16 +626,18 @@ void Source::ClangViewAutocomplete::autocomplete_check() {
const boost::regex within_namespace("^(.*)([^a-zA-Z0-9_]+)([a-zA-Z0-9_]{3,})$"); const boost::regex within_namespace("^(.*)([^a-zA-Z0-9_]+)([a-zA-Z0-9_]{3,})$");
boost::smatch sm; boost::smatch sm;
if(boost::regex_match(line, sm, in_specified_namespace)) { if(boost::regex_match(line, sm, in_specified_namespace)) {
prefix_mutex.lock(); {
std::unique_lock<std::mutex> lock(prefix_mutex);
prefix=sm[3].str(); prefix=sm[3].str();
prefix_mutex.unlock(); }
if(prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') if(prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9')
autocomplete(); autocomplete();
} }
else if(boost::regex_match(line, sm, within_namespace)) { else if(boost::regex_match(line, sm, within_namespace)) {
prefix_mutex.lock(); {
std::unique_lock<std::mutex> lock(prefix_mutex);
prefix=sm[3].str(); prefix=sm[3].str();
prefix_mutex.unlock(); }
if(prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') if(prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9')
autocomplete(); autocomplete();
} }
@ -667,7 +672,7 @@ void Source::ClangViewAutocomplete::autocomplete() {
pos--; pos--;
} }
autocomplete_thread=std::thread([this, line_nr, column_nr, buffer](){ autocomplete_thread=std::thread([this, line_nr, column_nr, buffer](){
parse_mutex.lock(); std::unique_lock<std::mutex> lock(parse_mutex);
if(parse_state==ParseState::PROCESSING) { if(parse_state==ParseState::PROCESSING) {
parse_process_state=ParseProcessState::IDLE; parse_process_state=ParseProcessState::IDLE;
auto autocomplete_data=std::make_shared<std::vector<AutoCompleteData> >(autocomplete_get_suggestions(buffer->raw(), line_nr, column_nr)); auto autocomplete_data=std::make_shared<std::vector<AutoCompleteData> >(autocomplete_get_suggestions(buffer->raw(), line_nr, column_nr));
@ -726,7 +731,6 @@ void Source::ClangViewAutocomplete::autocomplete() {
}); });
} }
} }
parse_mutex.unlock();
}); });
} }
@ -740,9 +744,10 @@ std::vector<Source::ClangViewAutocomplete::AutoCompleteData> Source::ClangViewAu
} }
if(autocomplete_state==AutocompleteState::STARTING) { if(autocomplete_state==AutocompleteState::STARTING) {
prefix_mutex.lock(); std::unique_lock<std::mutex> lock(prefix_mutex);
auto prefix_copy=prefix; auto prefix_copy=prefix;
prefix_mutex.unlock(); lock.unlock();
for (unsigned i = 0; i < results.size(); i++) { for (unsigned i = 0; i < results.size(); i++) {
auto result=results.get(i); auto result=results.get(i);
if(result.available()) { if(result.available()) {

61
src/terminal.cc

@ -9,9 +9,10 @@ Terminal::InProgress::InProgress(const std::string& start_msg): stop(false) {
} }
Terminal::InProgress::~InProgress() { Terminal::InProgress::~InProgress() {
stop_mutex.lock(); {
std::unique_lock<std::mutex> lock(stop_mutex);
stop=true; stop=true;
stop_mutex.unlock(); }
if(wait_thread.joinable()) if(wait_thread.joinable())
wait_thread.join(); wait_thread.join();
} }
@ -21,13 +22,11 @@ void Terminal::InProgress::start(const std::string& msg) {
wait_thread=std::thread([this](){ wait_thread=std::thread([this](){
size_t c=0; size_t c=0;
while(true) { while(true) {
stop_mutex.lock(); {
if(stop) { std::unique_lock<std::mutex> lock(stop_mutex);
stop_mutex.unlock(); if(stop)
break; break;
} }
else
stop_mutex.unlock();
if(c%100==0) if(c%100==0)
Terminal::get().async_print(line_nr-1, "."); Terminal::get().async_print(line_nr-1, ".");
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
@ -37,25 +36,21 @@ void Terminal::InProgress::start(const std::string& msg) {
} }
void Terminal::InProgress::done(const std::string& msg) { void Terminal::InProgress::done(const std::string& msg) {
stop_mutex.lock(); std::unique_lock<std::mutex> lock(stop_mutex);
if(!stop) { if(!stop) {
stop=true; stop=true;
stop_mutex.unlock(); lock.unlock();
Terminal::get().async_print(line_nr-1, msg); Terminal::get().async_print(line_nr-1, msg);
} }
else
stop_mutex.unlock();
} }
void Terminal::InProgress::cancel(const std::string& msg) { void Terminal::InProgress::cancel(const std::string& msg) {
stop_mutex.lock(); std::unique_lock<std::mutex> lock(stop_mutex);
if(!stop) { if(!stop) {
stop=true; stop=true;
stop_mutex.unlock(); lock.unlock();
Terminal::get().async_print(line_nr-1, msg); Terminal::get().async_print(line_nr-1, msg);
} }
else
stop_mutex.unlock();
} }
Terminal::Terminal() { Terminal::Terminal() {
@ -118,7 +113,7 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c
void Terminal::async_process(const std::string &command, const boost::filesystem::path &path, std::function<void(int exit_status)> callback) { void Terminal::async_process(const std::string &command, const boost::filesystem::path &path, std::function<void(int exit_status)> callback) {
std::thread async_execute_thread([this, command, path, callback](){ std::thread async_execute_thread([this, command, path, callback](){
processes_mutex.lock(); std::unique_lock<std::mutex> processes_lock(processes_mutex);
stdin_buffer.clear(); stdin_buffer.clear();
std::shared_ptr<Process> process(new Process(command, path.string(), [this](const char* bytes, size_t n) { std::shared_ptr<Process> process(new Process(command, path.string(), [this](const char* bytes, size_t n) {
async_print(std::string(bytes, n)); async_print(std::string(bytes, n));
@ -127,7 +122,7 @@ void Terminal::async_process(const std::string &command, const boost::filesystem
}, true)); }, true));
auto pid=process->get_id(); auto pid=process->get_id();
if (pid<=0) { if (pid<=0) {
processes_mutex.unlock(); processes_lock.unlock();
async_print("Error: failed to run command: " + command + "\n", true); async_print("Error: failed to run command: " + command + "\n", true);
if(callback) if(callback)
callback(-1); callback(-1);
@ -135,12 +130,12 @@ void Terminal::async_process(const std::string &command, const boost::filesystem
} }
else { else {
processes.emplace_back(process); processes.emplace_back(process);
processes_mutex.unlock(); processes_lock.unlock();
} }
auto exit_status=process->get_exit_status(); auto exit_status=process->get_exit_status();
processes_mutex.lock(); processes_lock = std::unique_lock<std::mutex>(processes_mutex);
for(auto it=processes.begin();it!=processes.end();it++) { for(auto it=processes.begin();it!=processes.end();it++) {
if((*it)->get_id()==pid) { if((*it)->get_id()==pid) {
processes.erase(it); processes.erase(it);
@ -148,7 +143,7 @@ void Terminal::async_process(const std::string &command, const boost::filesystem
} }
} }
stdin_buffer.clear(); stdin_buffer.clear();
processes_mutex.unlock(); processes_lock.unlock();
if(callback) if(callback)
callback(exit_status); callback(exit_status);
@ -157,17 +152,15 @@ void Terminal::async_process(const std::string &command, const boost::filesystem
} }
void Terminal::kill_last_async_process(bool force) { void Terminal::kill_last_async_process(bool force) {
processes_mutex.lock(); std::unique_lock<std::mutex> lock(processes_mutex);
if(processes.size()>0) if(processes.size()>0)
processes.back()->kill(force); processes.back()->kill(force);
processes_mutex.unlock();
} }
void Terminal::kill_async_processes(bool force) { void Terminal::kill_async_processes(bool force) {
processes_mutex.lock(); std::unique_lock<std::mutex> lock(processes_mutex);
for(auto &process: processes) for(auto &process: processes)
process->kill(force); process->kill(force);
processes_mutex.unlock();
} }
size_t Terminal::print(const std::string &message, bool bold){ size_t Terminal::print(const std::string &message, bool bold){
@ -223,14 +216,16 @@ size_t Terminal::print(const std::string &message, bool bold){
std::shared_ptr<Terminal::InProgress> Terminal::print_in_progress(std::string start_msg) { std::shared_ptr<Terminal::InProgress> Terminal::print_in_progress(std::string start_msg) {
auto in_progress=std::shared_ptr<Terminal::InProgress>(new Terminal::InProgress(start_msg), [this](Terminal::InProgress *in_progress) { auto in_progress=std::shared_ptr<Terminal::InProgress>(new Terminal::InProgress(start_msg), [this](Terminal::InProgress *in_progress) {
in_progresses_mutex.lock(); {
std::unique_lock<std::mutex> lock(in_progresses_mutex);
in_progresses.erase(in_progress); in_progresses.erase(in_progress);
in_progresses_mutex.unlock(); }
delete in_progress; delete in_progress;
}); });
in_progresses_mutex.lock(); {
std::unique_lock<std::mutex> lock(in_progresses_mutex);
in_progresses.emplace(in_progress.get()); in_progresses.emplace(in_progress.get());
in_progresses_mutex.unlock(); }
return in_progress; return in_progress;
} }
@ -277,20 +272,19 @@ void Terminal::configure() {
} }
void Terminal::clear() { void Terminal::clear() {
in_progresses_mutex.lock(); std::unique_lock<std::mutex> lock(in_progresses_mutex);
for(auto &in_progress: in_progresses) { for(auto &in_progress: in_progresses) {
in_progress->stop_mutex.lock(); std::unique_lock<std::mutex> stop_lock(in_progress->stop_mutex);
in_progress->stop=true; in_progress->stop=true;
in_progress->stop_mutex.unlock();
} }
in_progresses_mutex.unlock(); lock.unlock();
while(g_main_context_pending(NULL)) while(g_main_context_pending(NULL))
g_main_context_iteration(NULL, false); g_main_context_iteration(NULL, false);
get_buffer()->set_text(""); get_buffer()->set_text("");
} }
bool Terminal::on_key_press_event(GdkEventKey *event) { bool Terminal::on_key_press_event(GdkEventKey *event) {
processes_mutex.lock(); std::unique_lock<std::mutex> lock(processes_mutex);
bool debug_is_running=false; bool debug_is_running=false;
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
debug_is_running=Project::current_language?Project::current_language->debug_is_running():false; debug_is_running=Project::current_language?Project::current_language->debug_is_running():false;
@ -324,6 +318,5 @@ bool Terminal::on_key_press_event(GdkEventKey *event) {
stdin_buffer.clear(); stdin_buffer.clear();
} }
} }
processes_mutex.unlock();
return true; return true;
} }

Loading…
Cancel
Save