summaryrefslogtreecommitdiff
path: root/library/Core.cpp
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-03-15 15:33:19 +0400
committerAlexander Gavrilov2012-03-15 15:33:19 +0400
commit4eb481177737fe47cda80808dc4a62bd864a15e0 (patch)
treee41f625df61c782a110a68042593312c88e98b7b /library/Core.cpp
parent605ee9669a5cd4d2f69ca8adcbe96c9e62671b87 (diff)
downloaddfhack-4eb481177737fe47cda80808dc4a62bd864a15e0.tar.gz
dfhack-4eb481177737fe47cda80808dc4a62bd864a15e0.tar.bz2
dfhack-4eb481177737fe47cda80808dc4a62bd864a15e0.tar.xz
Make the DF suspend lock recursive, and add RPC calls for batch suspend.
The idea is that if you have to execute many RPC calls, it is faster to suspend once. The service class takes care to auto-resume in the destructor in case the client just disappears.
Diffstat (limited to 'library/Core.cpp')
-rw-r--r--library/Core.cpp95
1 files changed, 67 insertions, 28 deletions
diff --git a/library/Core.cpp b/library/Core.cpp
index 793a6368..928ad09e 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -98,6 +98,20 @@ struct Core::Cond
bool predicate;
};
+struct Core::Private
+{
+ tthread::mutex AccessMutex;
+ tthread::mutex StackMutex;
+ std::stack<Core::Cond*> suspended_tools;
+ Core::Cond core_cond;
+ thread::id df_suspend_thread;
+ int df_suspend_depth;
+
+ Private() {
+ df_suspend_depth = 0;
+ }
+};
+
void cheap_tokenise(string const& input, vector<string> &output)
{
string *cur = NULL;
@@ -550,6 +564,8 @@ void fIOthread(void * iodata)
Core::Core()
{
+ d = new Private();
+
// init the console. This must be always the first step!
plug_mgr = 0;
vif = 0;
@@ -559,10 +575,6 @@ Core::Core()
started = false;
memset(&(s_mods), 0, sizeof(s_mods));
- // create mutex for syncing with interactive tasks
- AccessMutex = 0;
- StackMutex = 0;
- core_cond = 0;
// set up hotkey capture
hotkey_set = false;
HotkeyMutex = 0;
@@ -661,10 +673,7 @@ bool Core::Init()
df::global::InitGlobals();
// create mutex for syncing with interactive tasks
- StackMutex = new mutex();
- AccessMutex = new mutex();
misc_data_mutex=new mutex();
- core_cond = new Core::Cond();
cerr << "Initializing Plugins.\n";
// create plugin manager
plug_mgr = new PluginManager(this);
@@ -757,22 +766,49 @@ void *Core::GetData( std::string key )
void Core::Suspend()
{
- Core::Cond * nc = new Core::Cond();
+ auto tid = this_thread::get_id();
+
+ // If recursive, just increment the count
+ {
+ lock_guard<mutex> lock(d->AccessMutex);
+
+ if (d->df_suspend_depth > 0 && d->df_suspend_thread == tid)
+ {
+ d->df_suspend_depth++;
+ return;
+ }
+ }
+
// put the condition on a stack
- StackMutex->lock();
- suspended_tools.push(nc);
- StackMutex->unlock();
+ Core::Cond *nc = new Core::Cond();
+
+ {
+ lock_guard<mutex> lock2(d->StackMutex);
+
+ d->suspended_tools.push(nc);
+ }
+
// wait until Core::Update() wakes up the tool
- AccessMutex->lock();
- nc->Lock(AccessMutex);
- AccessMutex->unlock();
+ {
+ lock_guard<mutex> lock(d->AccessMutex);
+
+ nc->Lock(&d->AccessMutex);
+
+ assert(d->df_suspend_depth == 0);
+ d->df_suspend_thread = tid;
+ d->df_suspend_depth = 1;
+ }
}
void Core::Resume()
{
- AccessMutex->lock();
- core_cond->Unlock();
- AccessMutex->unlock();
+ auto tid = this_thread::get_id();
+ lock_guard<mutex> lock(d->AccessMutex);
+
+ assert(d->df_suspend_depth > 0 && d->df_suspend_thread == tid);
+
+ if (--d->df_suspend_depth == 0)
+ d->core_cond.Unlock();
}
int Core::TileUpdate()
@@ -827,21 +863,24 @@ int Core::Update()
// wake waiting tools
// do not allow more tools to join in while we process stuff here
- StackMutex->lock();
- while (!suspended_tools.empty())
+ lock_guard<mutex> lock_stack(d->StackMutex);
+
+ while (!d->suspended_tools.empty())
{
- Core::Cond * nc = suspended_tools.top();
- suspended_tools.pop();
- AccessMutex->lock();
- // wake tool
- nc->Unlock();
- // wait for tool to wake us
- core_cond->Lock(AccessMutex);
- AccessMutex->unlock();
+ Core::Cond * nc = d->suspended_tools.top();
+ d->suspended_tools.pop();
+
+ lock_guard<mutex> lock(d->AccessMutex);
+ // wake tool
+ nc->Unlock();
+ // wait for tool to wake us
+ d->core_cond.Lock(&d->AccessMutex);
+ // verify
+ assert(d->df_suspend_depth == 0);
// destroy condition
delete nc;
}
- StackMutex->unlock();
+
return 0;
};