Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions library/Console-windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ bool Console::init(bool)
// FIXME: looks awfully empty, doesn't it?
bool Console::shutdown(void)
{
assert(inited);
std::lock_guard<std::recursive_mutex> lock{*wlock};
FreeConsole();
inited = false;
Expand Down
20 changes: 17 additions & 3 deletions library/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ namespace DFHack {
return Core::getInstance().getHackPath() / "data" / "dfhack-config-defaults";
};

Core* Core::active_instance = nullptr;

class MainThread {
public:
//! MainThread::suspend keeps the main DF thread suspended from Core::Init to
Expand Down Expand Up @@ -1077,6 +1079,11 @@ df::viewscreen * Core::getTopViewscreen() {
}

bool Core::InitMainThread(std::filesystem::path path) {
assert(active_instance == nullptr);

// set this instance as the active instance
active_instance = this;

// this hook is always called from DF's main (render) thread, so capture this thread id
df_render_thread = std::this_thread::get_id();
hack_path = path;
Expand Down Expand Up @@ -1490,8 +1497,8 @@ bool Core::InitSimulationThread()
}

Core& Core::getInstance() {
static Core instance;
return instance;
assert(Core::active_instance != nullptr);
return *Core::active_instance;
}

bool Core::isSuspended(void)
Expand Down Expand Up @@ -1921,20 +1928,27 @@ int Core::Shutdown ( void )

if (hotkey_mgr) {
delete hotkey_mgr;
hotkey_mgr = nullptr;
}

if(plug_mgr)
{
delete plug_mgr;
plug_mgr = nullptr;
}

// invalidate all modules
allModules.clear();
Textures::cleanup();
DFSDL::cleanup();
DFSteam::cleanup(getConsole());
DFSteam::cleanup();

memset(&(s_mods), 0, sizeof(s_mods));
d.reset();

// clear active instance
Core::active_instance = nullptr;

return -1;
}

Expand Down
3 changes: 0 additions & 3 deletions library/Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ void DebugManager::unregisterCategory(DebugCategory& cat)

DebugRegisterBase::DebugRegisterBase(DebugCategory* cat)
{
// Make sure Core lives at least as long any DebugCategory to
// allow debug prints until all Debugcategories has been destructed
Core::getInstance();
DebugManager::getInstance().registerCategory(*cat);
}

Expand Down
21 changes: 15 additions & 6 deletions library/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ DFhackCExport void dfhooks_preinit(std::filesystem::path dllpath)
basepath = dllpath.parent_path();
}

static std::unique_ptr<DFHack::Core> core_instance;

// called from the main thread before the simulation thread is started
// and the main event loop is initiated
DFhackCExport void dfhooks_init() {
Expand All @@ -49,8 +51,11 @@ DFhackCExport void dfhooks_init() {
return;
}

// construct DFHack core instance
core_instance = std::make_unique<DFHack::Core>();

// we need to init DF globals before we can check the commandline
if (!DFHack::Core::getInstance().InitMainThread(std::filesystem::canonical(basepath)) || !df::global::game) {
if (!core_instance->InitMainThread(std::filesystem::canonical(basepath)) || !df::global::game) {
// we don't set disabled to true here so symbol generation can work
return;
}
Expand All @@ -59,6 +64,8 @@ DFhackCExport void dfhooks_init() {
if (cmdline.find("--disable-dfhack") != std::string::npos) {
fprintf(stderr, "dfhack: --disable-dfhack specified on commandline; disabling\n");
disabled = true;
core_instance->Shutdown();
core_instance.reset();
return;
}

Expand All @@ -69,14 +76,16 @@ DFhackCExport void dfhooks_init() {
DFhackCExport void dfhooks_shutdown() {
if (disabled)
return;
DFHack::Core::getInstance().Shutdown();
core_instance->Shutdown();
// release DFHack core instance
core_instance.reset();
}

// called from the simulation thread in the main event loop
DFhackCExport void dfhooks_update() {
if (disabled)
return;
DFHack::Core::getInstance().Update();
core_instance->Update();
}

// called from the simulation thread just before adding the macro
Expand All @@ -92,7 +101,7 @@ DFhackCExport void dfhooks_prerender() {
DFhackCExport bool dfhooks_sdl_event(SDL_Event* event) {
if (disabled)
return false;
return DFHack::Core::getInstance().DFH_SDL_Event(event);
return core_instance->DFH_SDL_Event(event);
}

// called from the main thread just after setting mouse state in gps and just
Expand All @@ -101,7 +110,7 @@ DFhackCExport void dfhooks_sdl_loop() {
if (disabled)
return;
// TODO: wire this up to the new SDL-based console once it is merged
DFHack::Core::getInstance().DFH_SDL_Loop();
core_instance->DFH_SDL_Loop();
}

// called from the main thread for each utf-8 char read from the ncurses input
Expand All @@ -111,5 +120,5 @@ DFhackCExport void dfhooks_sdl_loop() {
DFhackCExport bool dfhooks_ncurses_key(int key) {
if (disabled)
return false;
return DFHack::Core::getInstance().DFH_ncurses_key(key);
return core_instance->DFH_ncurses_key(key);
}
12 changes: 9 additions & 3 deletions library/include/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,11 @@ namespace DFHack
friend void ::dfhooks_sdl_loop();
friend bool ::dfhooks_ncurses_key(int key);
public:
/// Get the single Core instance or make one.
/// Get the current active Core instance. will assert if none exists
/// Use noInstance() to check first if unsure
static Core& getInstance();
static bool noInstance() { return active_instance == nullptr; }

/// check if the activity lock is owned by this thread
bool isSuspended(void);
/// Is everything OK?
Expand Down Expand Up @@ -259,11 +262,14 @@ namespace DFHack
return false;
}

Core();
~Core();

private:
static Core* active_instance;

DFHack::Console con;

Core();
~Core();

struct Private;
std::unique_ptr<Private> d;
Expand Down
9 changes: 8 additions & 1 deletion library/include/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class DFHACK_EXPORT DebugCategory final {
};

/*!
* Fetch a steam object proxy object for output. It also adds standard
* Fetch a stream object proxy object for output. It also adds standard
* message components like time and plugin and category names to the line.
*
* User must make sure that the line is terminated with a line end.
Expand All @@ -194,6 +194,13 @@ class DFHACK_EXPORT DebugCategory final {
*/
ostream_proxy_prefix getStream(const level msgLevel) const
{
// if the core instance is unavailable, use stderr as a fallback
if (Core::noInstance())
{
static color_ostream_wrapper fallback{std::cerr};
return {*this,fallback,msgLevel};
}

return {*this,Core::getInstance().getConsole(),msgLevel};
}
/*!
Expand Down
2 changes: 1 addition & 1 deletion library/include/modules/DFSteam.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ bool init(DFHack::color_ostream& out);
/**
* Call this when DFHack is being unloaded.
*/
void cleanup(DFHack::color_ostream& out);
void cleanup();

DFHACK_EXPORT void launchSteamDFHackIfNecessary(DFHack::color_ostream& out);

Expand Down
35 changes: 24 additions & 11 deletions library/modules/DFSteam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,20 @@ bool (*g_SteamAPI_RestartAppIfNecessary)(uint32_t unOwnAppID) = nullptr;
void* (*g_SteamInternal_FindOrCreateUserInterface)(int, const char*) = nullptr;
bool (*g_SteamAPI_ISteamApps_BIsAppInstalled)(void *iSteamApps, uint32_t appID) = nullptr;

static void bind_all(color_ostream& out, DFLibrary* handle) {
#define bind(name) \
if (!handle) { \
g_##name = nullptr; \
} else { \
g_##name = (decltype(g_##name))LookupPlugin(handle, #name); \
if (!g_##name) { \
WARN(dfsteam, out).print("steam library function not found: " #name "\n"); \
} \
template<typename Ptr>
static void bind_(color_ostream& out, DFLibrary* handle, const char* name, Ptr& func_ptr) {
if (!handle) {
func_ptr = nullptr;
} else {
func_ptr = (Ptr)LookupPlugin(handle, name);
if (!func_ptr) {
WARN(dfsteam, out).print("steam library function not found: {}\n", name);
}
}
}

static void bind_all(color_ostream& out, DFLibrary* handle) {
#define bind(name) bind_(out, handle, #name, g_##name)
bind(SteamAPI_Init);
bind(SteamAPI_Shutdown);
bind(SteamAPI_GetHSteamUser);
Expand All @@ -56,6 +59,16 @@ static void bind_all(color_ostream& out, DFLibrary* handle) {
#undef bind
}

static void unbind_all()
{
g_SteamAPI_Init = nullptr;
g_SteamAPI_Shutdown = nullptr;
g_SteamAPI_GetHSteamUser = nullptr;
g_SteamInternal_FindOrCreateUserInterface = nullptr;
g_SteamAPI_RestartAppIfNecessary = nullptr;
g_SteamAPI_ISteamApps_BIsAppInstalled = nullptr;
}

bool DFSteam::init(color_ostream& out) {
char *steam_client_launch = getenv("SteamClientLaunch");
if (!steam_client_launch || strncmp(steam_client_launch, "1", 2) != 0) {
Expand Down Expand Up @@ -84,7 +97,7 @@ bool DFSteam::init(color_ostream& out) {
return true;
}

void DFSteam::cleanup(color_ostream& out) {
void DFSteam::cleanup() {
if (!g_steam_handle)
return;

Expand All @@ -94,7 +107,7 @@ void DFSteam::cleanup(color_ostream& out) {
ClosePlugin(g_steam_handle);
g_steam_handle = nullptr;

bind_all(out, nullptr);
unbind_all();
g_steam_initialized = false;
}

Expand Down
Loading