void Core::Suspend() { 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 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 { 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; } }
// should always be from simulation thread! int Core::Update() { if(!started) Init(); if(errorstate) return -1; // notify all the plugins that a game tick is finished plug_mgr->OnUpdate(); // wake waiting tools // do not allow more tools to join in while we process stuff here StackMutex->lock(); while (!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(); // destroy condition delete nc; } StackMutex->unlock(); return 0; };
// should always be from simulation thread! int Core::Update() { if(!started) Init(); if(errorstate) return -1; // detect if the game was loaded or unloaded in the meantime void *new_wdata = NULL; if (df::global::world) { df::world_data *wdata = df::global::world->world_data; // when the game is unloaded, world_data isn't deleted, but its contents are if (wdata && !wdata->sites.empty()) new_wdata = wdata; } if (new_wdata != last_world_data_ptr) { last_world_data_ptr = new_wdata; plug_mgr->OnStateChange(new_wdata ? SC_GAME_LOADED : SC_GAME_UNLOADED); } // detect if the viewscreen changed if (df::global::gview) { df::viewscreen *screen = &df::global::gview->view; while (screen->child) screen = screen->child; if (screen != top_viewscreen) { top_viewscreen = screen; plug_mgr->OnStateChange(SC_VIEWSCREEN_CHANGED); } } // notify all the plugins that a game tick is finished plug_mgr->OnUpdate(); // wake waiting tools // do not allow more tools to join in while we process stuff here StackMutex->lock(); while (!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(); // destroy condition delete nc; } StackMutex->unlock(); return 0; };
void Core::Suspend() { Core::Cond * nc = new Core::Cond(); // put the condition on a stack StackMutex->lock(); suspended_tools.push(nc); StackMutex->unlock(); // wait until Core::Update() wakes up the tool AccessMutex->lock(); nc->Lock(AccessMutex); AccessMutex->unlock(); }
// should always be from simulation thread! int Core::Update() { if(errorstate) return -1; color_ostream_proxy out(con); // Pretend this thread has suspended the core in the usual way, // and run various processing hooks. { CoreSuspendClaimer suspend(true); // Initialize the core bool first_update = false; if(!started) { first_update = true; Init(); if(errorstate) return -1; Lua::Core::Reset(con, "core init"); } doUpdate(out, first_update); } // wake waiting tools // do not allow more tools to join in while we process stuff here lock_guard<mutex> lock_stack(d->StackMutex); while (!d->suspended_tools.empty()) { 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; // check lua stack depth Lua::Core::Reset(out, "suspend"); } return 0; };