Make sure hotkeythread exits before cleanup

develop
Pauli 2018-06-21 17:13:22 +03:00
parent 1fc37f8ddc
commit 0bc1db4f07
2 changed files with 33 additions and 10 deletions

@ -131,6 +131,7 @@ struct Core::Private
thread::id df_suspend_thread; thread::id df_suspend_thread;
int df_suspend_depth; int df_suspend_depth;
std::thread iothread; std::thread iothread;
std::thread hotkeythread;
Private() { Private() {
df_suspend_depth = 0; df_suspend_depth = 0;
@ -224,9 +225,10 @@ void fHKthread(void * iodata)
cerr << "Hotkey thread has croaked." << endl; cerr << "Hotkey thread has croaked." << endl;
return; return;
} }
while(1) bool keep_going = true;
while(keep_going)
{ {
std::string stuff = core->getHotkeyCmd(); // waits on mutex! std::string stuff = core->getHotkeyCmd(keep_going); // waits on mutex!
if(!stuff.empty()) if(!stuff.empty())
{ {
color_ostream_proxy out(core->getConsole()); color_ostream_proxy out(core->getConsole());
@ -1479,6 +1481,11 @@ void fIOthread(void * iodata)
Core::~Core() Core::~Core()
{ {
if (d->hotkeythread.joinable()) {
std::lock_guard<std::mutex> lock(HotkeyMutex);
hotkey_set = SHUTDOWN;
HotkeyCond.notify_one();
}
if (d->iothread.joinable()) if (d->iothread.joinable())
con.shutdown(); con.shutdown();
delete d; delete d;
@ -1502,7 +1509,7 @@ Core::Core() :
memset(&(s_mods), 0, sizeof(s_mods)); memset(&(s_mods), 0, sizeof(s_mods));
// set up hotkey capture // set up hotkey capture
hotkey_set = false; hotkey_set = NO;
last_world_data_ptr = NULL; last_world_data_ptr = NULL;
last_local_map_ptr = NULL; last_local_map_ptr = NULL;
last_pause_state = false; last_pause_state = false;
@ -1756,8 +1763,7 @@ bool Core::Init()
cerr << "Starting DF input capture thread.\n"; cerr << "Starting DF input capture thread.\n";
// set up hotkey capture // set up hotkey capture
thread * HK = new thread(fHKthread, (void *) temp); d->hotkeythread = std::thread(fHKthread, (void *) temp);
(void)HK;
screen_window = new Windows::top_level_window(); screen_window = new Windows::top_level_window();
screen_window->addChild(new Windows::dfhack_dummy(5,10)); screen_window->addChild(new Windows::dfhack_dummy(5,10));
started = true; started = true;
@ -1837,18 +1843,22 @@ bool Core::setHotkeyCmd( std::string cmd )
{ {
// access command // access command
std::lock_guard<std::mutex> lock(HotkeyMutex); std::lock_guard<std::mutex> lock(HotkeyMutex);
hotkey_set = true; hotkey_set = SET;
hotkey_cmd = cmd; hotkey_cmd = cmd;
HotkeyCond.notify_all(); HotkeyCond.notify_all();
return true; return true;
} }
/// removes the hotkey command and gives it to the caller thread /// removes the hotkey command and gives it to the caller thread
std::string Core::getHotkeyCmd( void ) std::string Core::getHotkeyCmd( bool &keep_going )
{ {
string returner; string returner;
std::unique_lock<std::mutex> lock(HotkeyMutex); std::unique_lock<std::mutex> lock(HotkeyMutex);
HotkeyCond.wait(lock, [this]() -> bool {return this->hotkey_set;}); HotkeyCond.wait(lock, [this]() -> bool {return this->hotkey_set;});
hotkey_set = false; if (hotkey_set == SHUTDOWN) {
keep_going = false;
return returner;
}
hotkey_set = NO;
returner = hotkey_cmd; returner = hotkey_cmd;
hotkey_cmd.clear(); hotkey_cmd.clear();
return returner; return returner;
@ -2357,6 +2367,14 @@ int Core::Shutdown ( void )
if(errorstate) if(errorstate)
return true; return true;
errorstate = 1; errorstate = 1;
if (d->hotkeythread.joinable()) {
std::unique_lock<std::mutex> hot_lock(HotkeyMutex);
hotkey_set = SHUTDOWN;
HotkeyCond.notify_one();
}
d->hotkeythread.join();
CoreSuspendClaimer suspend; CoreSuspendClaimer suspend;
if(plug_mgr) if(plug_mgr)
{ {

@ -145,7 +145,7 @@ namespace DFHack
/// sets the current hotkey command /// sets the current hotkey command
bool setHotkeyCmd( std::string cmd ); bool setHotkeyCmd( std::string cmd );
/// removes the hotkey command and gives it to the caller thread /// removes the hotkey command and gives it to the caller thread
std::string getHotkeyCmd( void ); std::string getHotkeyCmd( bool &keep_going );
/// adds a named pointer (for later or between plugins) /// adds a named pointer (for later or between plugins)
void RegisterData(void *p,std::string key); void RegisterData(void *p,std::string key);
@ -257,7 +257,12 @@ namespace DFHack
std::map<int, std::vector<KeyBinding> > key_bindings; std::map<int, std::vector<KeyBinding> > key_bindings;
std::map<int, bool> hotkey_states; std::map<int, bool> hotkey_states;
std::string hotkey_cmd; std::string hotkey_cmd;
bool hotkey_set; enum hotkey_set_t {
NO,
SET,
SHUTDOWN,
};
hotkey_set_t hotkey_set;
std::mutex HotkeyMutex; std::mutex HotkeyMutex;
std::condition_variable HotkeyCond; std::condition_variable HotkeyCond;