diff --git a/Subsurface-mobile.pro b/Subsurface-mobile.pro index e5c5d6767..b910be2db 100644 --- a/Subsurface-mobile.pro +++ b/Subsurface-mobile.pro @@ -57,6 +57,7 @@ SOURCES += subsurface-mobile-main.cpp \ core/gas-model.c \ core/gaspressures.c \ core/git-access.c \ + core/globals.cpp \ core/liquivision.c \ core/load-git.c \ core/parse-xml.c \ @@ -201,6 +202,7 @@ HEADERS += \ core/event.h \ core/extradata.h \ core/git-access.h \ + core/globals.h \ core/pref.h \ core/profile.h \ core/qthelper.h \ diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 9dc2ddb8b..2fe7a7707 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -105,6 +105,8 @@ set(SUBSURFACE_CORE_LIB_SRCS gettextfromc.h git-access.c git-access.h + globals.cpp + globals.h imagedownloader.cpp imagedownloader.h import-cobalt.c diff --git a/core/globals.cpp b/core/globals.cpp new file mode 100644 index 000000000..1516c5a5a --- /dev/null +++ b/core/globals.cpp @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "globals.h" + +#include + +static std::vector global_objects; + +void register_global_internal(GlobalObjectBase *o) +{ + global_objects.push_back(o); +} + +void free_globals() +{ + // We free the objects by hand, so that we can free them in reverse + // order of creation. AFAIK, order-of-destruction is implementantion-defined + // for std::vector<>. + for (auto it = global_objects.rbegin(); it != global_objects.rend(); ++it) + delete *it; + global_objects.clear(); +} diff --git a/core/globals.h b/core/globals.h new file mode 100644 index 000000000..524c0c8fb --- /dev/null +++ b/core/globals.h @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +// Collection of objects that will be deleted on application exit. +// This feature is needed because many Qt-objects crash if freed +// after the application has exited. +#ifndef GLOBALS_H +#define GLOBALS_H + +#include +#include + +template +T *make_global(Args &&...args); // construct a global object of type T. + +template +T *register_global(T *); // register an already constructed object. returns input. + +void free_globals(); // call on application exit. frees all global objects. + +// Implementation + +// A class with a virtual destructor that will be used to destruct the objects. +struct GlobalObjectBase +{ + virtual ~GlobalObjectBase() { } +}; + +template +struct GlobalObject : T, GlobalObjectBase +{ + using T::T; // Inherit constructor from actual object. +}; + +void register_global_internal(GlobalObjectBase *); + +template +T *make_global(Args &&...args) +{ + GlobalObject *res = new GlobalObject(std::forward(args)...); + register_global_internal(res); + return res; +} + +template +T *register_global(T *o) +{ + make_global>(o); + return o; +} + +#endif diff --git a/subsurface-helper.cpp b/subsurface-helper.cpp index 193a472b5..e0d8f18d6 100644 --- a/subsurface-helper.cpp +++ b/subsurface-helper.cpp @@ -8,6 +8,7 @@ #endif #include "stats/statsview.h" +#include "core/globals.h" #include "core/qt-gui.h" #include "core/settings/qPref.h" #include "core/ssrf.h" @@ -67,6 +68,7 @@ void exit_ui() #ifndef SUBSURFACE_MOBILE delete MainWindow::instance(); #endif // SUBSURFACE_MOBILE + free_globals(); free((void *)existing_filename); }