diff --git a/library/Core.cpp b/library/Core.cpp index d584cb891..d16b5378d 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -131,6 +131,7 @@ struct Core::Private thread::id df_suspend_thread; int df_suspend_depth; std::thread iothread; + std::thread hotkeythread; Private() { df_suspend_depth = 0; @@ -224,9 +225,10 @@ void fHKthread(void * iodata) cerr << "Hotkey thread has croaked." << endl; 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()) { color_ostream_proxy out(core->getConsole()); @@ -1479,6 +1481,11 @@ void fIOthread(void * iodata) Core::~Core() { + if (d->hotkeythread.joinable()) { + std::lock_guard lock(HotkeyMutex); + hotkey_set = SHUTDOWN; + HotkeyCond.notify_one(); + } if (d->iothread.joinable()) con.shutdown(); delete d; @@ -1502,7 +1509,7 @@ Core::Core() : memset(&(s_mods), 0, sizeof(s_mods)); // set up hotkey capture - hotkey_set = false; + hotkey_set = NO; last_world_data_ptr = NULL; last_local_map_ptr = NULL; last_pause_state = false; @@ -1756,8 +1763,7 @@ bool Core::Init() cerr << "Starting DF input capture thread.\n"; // set up hotkey capture - thread * HK = new thread(fHKthread, (void *) temp); - (void)HK; + d->hotkeythread = std::thread(fHKthread, (void *) temp); screen_window = new Windows::top_level_window(); screen_window->addChild(new Windows::dfhack_dummy(5,10)); started = true; @@ -1837,18 +1843,22 @@ bool Core::setHotkeyCmd( std::string cmd ) { // access command std::lock_guard lock(HotkeyMutex); - hotkey_set = true; + hotkey_set = SET; hotkey_cmd = cmd; HotkeyCond.notify_all(); return true; } /// 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; std::unique_lock lock(HotkeyMutex); 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; hotkey_cmd.clear(); return returner; @@ -2357,6 +2367,14 @@ int Core::Shutdown ( void ) if(errorstate) return true; errorstate = 1; + if (d->hotkeythread.joinable()) { + std::unique_lock hot_lock(HotkeyMutex); + hotkey_set = SHUTDOWN; + HotkeyCond.notify_one(); + } + + d->hotkeythread.join(); + CoreSuspendClaimer suspend; if(plug_mgr) { diff --git a/library/include/Core.h b/library/include/Core.h index 6e3bd718e..2621bac21 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -145,7 +145,7 @@ namespace DFHack /// sets the current hotkey command bool setHotkeyCmd( std::string cmd ); /// 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) void RegisterData(void *p,std::string key); @@ -257,7 +257,12 @@ namespace DFHack std::map > key_bindings; std::map hotkey_states; std::string hotkey_cmd; - bool hotkey_set; + enum hotkey_set_t { + NO, + SET, + SHUTDOWN, + }; + hotkey_set_t hotkey_set; std::mutex HotkeyMutex; std::condition_variable HotkeyCond;