Convert Core.cpp to use c++11 thread

I noticed that tthread is missing some c++11 features that make thread
handling code a bit easier. To be able to use those features I decided
to convert Core.cpp to use equivalent standard classes.

This patch has no functional changes.
develop
Pauli 2018-06-12 17:33:12 +03:00
parent b7871c7368
commit 19a169ba65
3 changed files with 61 additions and 87 deletions

@ -77,7 +77,9 @@ using namespace DFHack;
#include <iomanip> #include <iomanip>
#include <stdlib.h> #include <stdlib.h>
#include <fstream> #include <fstream>
#include "tinythread.h" #include <thread>
#include <mutex>
#include <condition_variable>
#include "md5wrapper.h" #include "md5wrapper.h"
#include "SDL_events.h" #include "SDL_events.h"
@ -86,7 +88,6 @@ using namespace DFHack;
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
using namespace tthread;
using namespace df::enums; using namespace df::enums;
using df::global::init; using df::global::init;
using df::global::world; using df::global::world;
@ -96,40 +97,35 @@ using df::global::world;
static bool parseKeySpec(std::string keyspec, int *psym, int *pmod, std::string *pfocus = NULL); static bool parseKeySpec(std::string keyspec, int *psym, int *pmod, std::string *pfocus = NULL);
size_t loadScriptFiles(Core* core, color_ostream& out, const vector<std::string>& prefix, const std::string& folder); size_t loadScriptFiles(Core* core, color_ostream& out, const vector<std::string>& prefix, const std::string& folder);
struct Core::Cond struct Core::Cond : public std::condition_variable
{ {
Cond() Cond() :
std::condition_variable{},
predicate{false}
{ {
predicate = false;
wakeup = new tthread::condition_variable();
} }
~Cond() ~Cond()
{ {
delete wakeup;
} }
bool Lock(tthread::mutex * m) bool Lock(std::unique_lock<std::mutex>& lock)
{
while(!predicate)
{ {
wakeup->wait(*m); wait(lock, [this]() -> bool {return this->predicate;});
}
predicate = false; predicate = false;
return true; return true;
} }
bool Unlock() bool Unlock()
{ {
predicate = true; predicate = true;
wakeup->notify_one(); notify_one();
return true; return true;
} }
tthread::condition_variable * wakeup;
bool predicate; bool predicate;
}; };
struct Core::Private struct Core::Private
{ {
tthread::mutex AccessMutex; std::mutex AccessMutex;
tthread::mutex StackMutex; std::mutex StackMutex;
std::stack<Core::Cond*> suspended_tools; std::stack<Core::Cond*> suspended_tools;
Core::Cond core_cond; Core::Cond core_cond;
thread::id df_suspend_thread; thread::id df_suspend_thread;
@ -510,7 +506,7 @@ static bool try_autocomplete(color_ostream &con, const std::string &first, std::
bool Core::addScriptPath(string path, bool search_before) bool Core::addScriptPath(string path, bool search_before)
{ {
lock_guard<mutex> lock(*script_path_mutex); lock_guard<mutex> lock(script_path_mutex);
vector<string> &vec = script_paths[search_before ? 0 : 1]; vector<string> &vec = script_paths[search_before ? 0 : 1];
if (std::find(vec.begin(), vec.end(), path) != vec.end()) if (std::find(vec.begin(), vec.end(), path) != vec.end())
return false; return false;
@ -522,7 +518,7 @@ bool Core::addScriptPath(string path, bool search_before)
bool Core::removeScriptPath(string path) bool Core::removeScriptPath(string path)
{ {
lock_guard<mutex> lock(*script_path_mutex); lock_guard<mutex> lock(script_path_mutex);
bool found = false; bool found = false;
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
@ -541,7 +537,7 @@ bool Core::removeScriptPath(string path)
void Core::getScriptPaths(std::vector<std::string> *dest) void Core::getScriptPaths(std::vector<std::string> *dest)
{ {
lock_guard<mutex> lock(*script_path_mutex); lock_guard<mutex> lock(script_path_mutex);
dest->clear(); dest->clear();
string df_path = this->p->getPath(); string df_path = this->p->getPath();
for (auto it = script_paths[0].begin(); it != script_paths[0].end(); ++it) for (auto it = script_paths[0].begin(); it != script_paths[0].end(); ++it)
@ -1480,10 +1476,15 @@ void fIOthread(void * iodata)
} }
} }
Core::Core()
{
d = new Private();
Core::Core() :
d{new Private},
script_path_mutex{},
HotkeyMutex{},
HotkeyCond{},
alias_mutex{},
misc_data_mutex{}
{
// init the console. This must be always the first step! // init the console. This must be always the first step!
plug_mgr = 0; plug_mgr = 0;
vif = 0; vif = 0;
@ -1495,10 +1496,6 @@ Core::Core()
// set up hotkey capture // set up hotkey capture
hotkey_set = false; hotkey_set = false;
HotkeyMutex = 0;
HotkeyCond = 0;
alias_mutex = 0;
misc_data_mutex = 0;
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;
@ -1508,7 +1505,6 @@ Core::Core()
color_ostream::log_errors_to_stderr = true; color_ostream::log_errors_to_stderr = true;
script_path_mutex = new mutex();
}; };
void Core::fatal (std::string output) void Core::fatal (std::string output)
@ -1642,7 +1638,6 @@ bool Core::Init()
// Init global object pointers // Init global object pointers
df::global::InitGlobals(); df::global::InitGlobals();
alias_mutex = new recursive_mutex();
cerr << "Initializing Console.\n"; cerr << "Initializing Console.\n";
// init the console. // init the console.
@ -1732,7 +1727,6 @@ bool Core::Init()
} }
// create mutex for syncing with interactive tasks // create mutex for syncing with interactive tasks
misc_data_mutex=new mutex();
cerr << "Initializing Plugins.\n"; cerr << "Initializing Plugins.\n";
// create plugin manager // create plugin manager
plug_mgr = new PluginManager(this); plug_mgr = new PluginManager(this);
@ -1741,21 +1735,16 @@ bool Core::Init()
temp->core = this; temp->core = this;
temp->plug_mgr = plug_mgr; temp->plug_mgr = plug_mgr;
HotkeyMutex = new mutex();
HotkeyCond = new condition_variable();
if (!is_text_mode || is_headless) if (!is_text_mode || is_headless)
{ {
cerr << "Starting IO thread.\n"; cerr << "Starting IO thread.\n";
// create IO thread // create IO thread
thread * IO = new thread(fIOthread, (void *) temp); new thread(fIOthread, (void *) temp);
(void)IO;
} }
else else
{ {
cerr << "Starting dfhack.init thread.\n"; cerr << "Starting dfhack.init thread.\n";
thread * init = new thread(fInitthread, (void *) temp); new thread(fInitthread, (void *) temp);
(void)init;
} }
cerr << "Starting DF input capture thread.\n"; cerr << "Starting DF input capture thread.\n";
@ -1840,28 +1829,21 @@ bool Core::Init()
bool Core::setHotkeyCmd( std::string cmd ) bool Core::setHotkeyCmd( std::string cmd )
{ {
// access command // access command
HotkeyMutex->lock(); std::lock_guard<std::mutex> lock(HotkeyMutex);
{
hotkey_set = true; hotkey_set = true;
hotkey_cmd = cmd; hotkey_cmd = cmd;
HotkeyCond->notify_all(); HotkeyCond.notify_all();
}
HotkeyMutex->unlock();
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( void )
{ {
string returner; string returner;
HotkeyMutex->lock(); std::unique_lock<std::mutex> lock(HotkeyMutex);
while ( ! hotkey_set ) HotkeyCond.wait(lock, [this]() -> bool {return this->hotkey_set;});
{
HotkeyCond->wait(*HotkeyMutex);
}
hotkey_set = false; hotkey_set = false;
returner = hotkey_cmd; returner = hotkey_cmd;
hotkey_cmd.clear(); hotkey_cmd.clear();
HotkeyMutex->unlock();
return returner; return returner;
} }
@ -1887,25 +1869,22 @@ void Core::printerr(const char *format, ...)
void Core::RegisterData( void *p, std::string key ) void Core::RegisterData( void *p, std::string key )
{ {
misc_data_mutex->lock(); std::lock_guard<std::mutex> lock(misc_data_mutex);
misc_data_map[key] = p; misc_data_map[key] = p;
misc_data_mutex->unlock();
} }
void *Core::GetData( std::string key ) void *Core::GetData( std::string key )
{ {
misc_data_mutex->lock(); std::lock_guard<std::mutex> lock(misc_data_mutex);
std::map<std::string,void*>::iterator it=misc_data_map.find(key); std::map<std::string,void*>::iterator it=misc_data_map.find(key);
if ( it != misc_data_map.end() ) if ( it != misc_data_map.end() )
{ {
void *p=it->second; void *p=it->second;
misc_data_mutex->unlock();
return p; return p;
} }
else else
{ {
misc_data_mutex->unlock();
return 0;// or throw an error. return 0;// or throw an error.
} }
} }
@ -1943,9 +1922,9 @@ void Core::Suspend()
// wait until Core::Update() wakes up the tool // wait until Core::Update() wakes up the tool
{ {
lock_guard<mutex> lock(d->AccessMutex); unique_lock<mutex> lock(d->AccessMutex);
nc->Lock(&d->AccessMutex); nc->Lock(lock);
assert(d->df_suspend_depth == 0); assert(d->df_suspend_depth == 0);
d->df_suspend_thread = tid; d->df_suspend_thread = tid;
@ -2135,11 +2114,11 @@ int Core::Update()
Core::Cond * nc = d->suspended_tools.top(); Core::Cond * nc = d->suspended_tools.top();
d->suspended_tools.pop(); d->suspended_tools.pop();
lock_guard<mutex> lock(d->AccessMutex); std::unique_lock<mutex> lock(d->AccessMutex);
// wake tool // wake tool
nc->Unlock(); nc->Unlock();
// wait for tool to wake us // wait for tool to wake us
d->core_cond.Lock(&d->AccessMutex); d->core_cond.Lock(lock);
// verify // verify
assert(d->df_suspend_depth == 0); assert(d->df_suspend_depth == 0);
// destroy condition // destroy condition
@ -2530,7 +2509,7 @@ bool Core::SelectHotkey(int sym, int modifiers)
std::string cmd; std::string cmd;
{ {
tthread::lock_guard<tthread::mutex> lock(*HotkeyMutex); std::lock_guard<std::mutex> lock(HotkeyMutex);
// Check the internal keybindings // Check the internal keybindings
std::vector<KeyBinding> &bindings = key_bindings[sym]; std::vector<KeyBinding> &bindings = key_bindings[sym];
@ -2629,7 +2608,7 @@ bool Core::ClearKeyBindings(std::string keyspec)
if (!parseKeySpec(keyspec, &sym, &mod, &focus)) if (!parseKeySpec(keyspec, &sym, &mod, &focus))
return false; return false;
tthread::lock_guard<tthread::mutex> lock(*HotkeyMutex); std::lock_guard<std::mutex> lock(HotkeyMutex);
std::vector<KeyBinding> &bindings = key_bindings[sym]; std::vector<KeyBinding> &bindings = key_bindings[sym];
for (int i = bindings.size()-1; i >= 0; --i) { for (int i = bindings.size()-1; i >= 0; --i) {
@ -2668,7 +2647,7 @@ bool Core::AddKeyBinding(std::string keyspec, std::string cmdline)
if (binding.command.empty()) if (binding.command.empty())
return false; return false;
tthread::lock_guard<tthread::mutex> lock(*HotkeyMutex); std::lock_guard<std::mutex> lock(HotkeyMutex);
// Don't add duplicates // Don't add duplicates
std::vector<KeyBinding> &bindings = key_bindings[sym]; std::vector<KeyBinding> &bindings = key_bindings[sym];
@ -2692,7 +2671,7 @@ std::vector<std::string> Core::ListKeyBindings(std::string keyspec)
if (!parseKeySpec(keyspec, &sym, &mod, &focus)) if (!parseKeySpec(keyspec, &sym, &mod, &focus))
return rv; return rv;
tthread::lock_guard<tthread::mutex> lock(*HotkeyMutex); std::lock_guard<std::mutex> lock(HotkeyMutex);
std::vector<KeyBinding> &bindings = key_bindings[sym]; std::vector<KeyBinding> &bindings = key_bindings[sym];
for (int i = bindings.size()-1; i >= 0; --i) { for (int i = bindings.size()-1; i >= 0; --i) {
@ -2712,7 +2691,7 @@ std::vector<std::string> Core::ListKeyBindings(std::string keyspec)
bool Core::AddAlias(const std::string &name, const std::vector<std::string> &command, bool replace) bool Core::AddAlias(const std::string &name, const std::vector<std::string> &command, bool replace)
{ {
tthread::lock_guard<tthread::recursive_mutex> lock(*alias_mutex); std::lock_guard<std::recursive_mutex> lock(alias_mutex);
if (!IsAlias(name) || replace) if (!IsAlias(name) || replace)
{ {
aliases[name] = command; aliases[name] = command;
@ -2723,7 +2702,7 @@ bool Core::AddAlias(const std::string &name, const std::vector<std::string> &com
bool Core::RemoveAlias(const std::string &name) bool Core::RemoveAlias(const std::string &name)
{ {
tthread::lock_guard<tthread::recursive_mutex> lock(*alias_mutex); std::lock_guard<std::recursive_mutex> lock(alias_mutex);
if (IsAlias(name)) if (IsAlias(name))
{ {
aliases.erase(name); aliases.erase(name);
@ -2734,14 +2713,14 @@ bool Core::RemoveAlias(const std::string &name)
bool Core::IsAlias(const std::string &name) bool Core::IsAlias(const std::string &name)
{ {
tthread::lock_guard<tthread::recursive_mutex> lock(*alias_mutex); std::lock_guard<std::recursive_mutex> lock(alias_mutex);
return aliases.find(name) != aliases.end(); return aliases.find(name) != aliases.end();
} }
bool Core::RunAlias(color_ostream &out, const std::string &name, bool Core::RunAlias(color_ostream &out, const std::string &name,
const std::vector<std::string> &parameters, command_result &result) const std::vector<std::string> &parameters, command_result &result)
{ {
tthread::lock_guard<tthread::recursive_mutex> lock(*alias_mutex); std::lock_guard<std::recursive_mutex> lock(alias_mutex);
if (!IsAlias(name)) if (!IsAlias(name))
{ {
return false; return false;
@ -2756,13 +2735,13 @@ bool Core::RunAlias(color_ostream &out, const std::string &name,
std::map<std::string, std::vector<std::string>> Core::ListAliases() std::map<std::string, std::vector<std::string>> Core::ListAliases()
{ {
tthread::lock_guard<tthread::recursive_mutex> lock(*alias_mutex); std::lock_guard<std::recursive_mutex> lock(alias_mutex);
return aliases; return aliases;
} }
std::string Core::GetAliasCommand(const std::string &name, const std::string &default_) std::string Core::GetAliasCommand(const std::string &name, const std::string &default_)
{ {
tthread::lock_guard<tthread::recursive_mutex> lock(*alias_mutex); std::lock_guard<std::recursive_mutex> lock(alias_mutex);
if (IsAlias(name)) if (IsAlias(name))
return join_strings(" ", aliases[name]); return join_strings(" ", aliases[name]);
else else

@ -49,7 +49,6 @@ using namespace DFHack;
using namespace std; using namespace std;
#include "tinythread.h" #include "tinythread.h"
using namespace tthread;
#include <assert.h> #include <assert.h>
@ -83,8 +82,8 @@ struct Plugin::RefLock
RefLock() RefLock()
{ {
refcount = 0; refcount = 0;
wakeup = new condition_variable(); wakeup = new tthread::condition_variable();
mut = new mutex(); mut = new tthread::mutex();
} }
~RefLock() ~RefLock()
{ {
@ -119,8 +118,8 @@ struct Plugin::RefLock
wakeup->wait(*mut); wakeup->wait(*mut);
} }
} }
condition_variable * wakeup; tthread::condition_variable * wakeup;
mutex * mut; tthread::mutex * mut;
int refcount; int refcount;
}; };
@ -786,8 +785,8 @@ void Plugin::push_function(lua_State *state, LuaFunction *fn)
PluginManager::PluginManager(Core * core) : core(core) PluginManager::PluginManager(Core * core) : core(core)
{ {
plugin_mutex = new recursive_mutex(); plugin_mutex = new tthread::recursive_mutex();
cmdlist_mutex = new mutex(); cmdlist_mutex = new tthread::mutex();
ruby = NULL; ruby = NULL;
} }

@ -34,6 +34,9 @@ distribution.
#include "Console.h" #include "Console.h"
#include "modules/Graphic.h" #include "modules/Graphic.h"
#include <mutex>
#include <condition_variable>
#include "RemoteClient.h" #include "RemoteClient.h"
#define DFH_MOD_SHIFT 1 #define DFH_MOD_SHIFT 1
@ -42,13 +45,6 @@ distribution.
struct WINDOW; struct WINDOW;
namespace tthread
{
class mutex;
class condition_variable;
class thread;
}
namespace df namespace df
{ {
struct viewscreen; struct viewscreen;
@ -246,7 +242,7 @@ namespace DFHack
DFHack::PluginManager * plug_mgr; DFHack::PluginManager * plug_mgr;
std::vector<std::string> script_paths[2]; std::vector<std::string> script_paths[2];
tthread::mutex *script_path_mutex; std::mutex script_path_mutex;
// hotkey-related stuff // hotkey-related stuff
struct KeyBinding { struct KeyBinding {
@ -261,11 +257,11 @@ namespace DFHack
std::map<int, bool> hotkey_states; std::map<int, bool> hotkey_states;
std::string hotkey_cmd; std::string hotkey_cmd;
bool hotkey_set; bool hotkey_set;
tthread::mutex * HotkeyMutex; std::mutex HotkeyMutex;
tthread::condition_variable * HotkeyCond; std::condition_variable HotkeyCond;
std::map<std::string, std::vector<std::string>> aliases; std::map<std::string, std::vector<std::string>> aliases;
tthread::recursive_mutex * alias_mutex; std::recursive_mutex alias_mutex;
bool SelectHotkey(int key, int modifiers); bool SelectHotkey(int key, int modifiers);
@ -280,7 +276,7 @@ namespace DFHack
// Additional state change scripts // Additional state change scripts
std::vector<StateChangeScript> state_change_scripts; std::vector<StateChangeScript> state_change_scripts;
tthread::mutex * misc_data_mutex; std::mutex misc_data_mutex;
std::map<std::string,void*> misc_data_map; std::map<std::string,void*> misc_data_map;
friend class CoreService; friend class CoreService;