Implementing a test whether the current thread is the main (UI) thread

and using it on AppConfig::save() to assert if save is called
from a worker thread.
The old assert was using thread names, which did not always work
on Windows.
Fixes #7839 #9178 #9370 #9420
This commit is contained in:
Vojtech Bubnik 2023-02-07 16:17:26 +01:00
parent 340b685a0d
commit 8472287601
4 changed files with 31 additions and 6 deletions

View File

@ -72,6 +72,8 @@ int CLI::run(int argc, char **argv)
{ {
// Mark the main thread for the debugger and for runtime checks. // Mark the main thread for the debugger and for runtime checks.
set_current_thread_name("slic3r_main"); set_current_thread_name("slic3r_main");
// Save the thread ID of the main thread.
save_main_thread_id();
#ifdef __WXGTK__ #ifdef __WXGTK__
// On Linux, wxGTK has no support for Wayland, and the app crashes on // On Linux, wxGTK has no support for Wayland, and the app crashes on

View File

@ -417,12 +417,8 @@ std::string AppConfig::load()
void AppConfig::save() void AppConfig::save()
{ {
{ if (! is_main_thread_active())
// Returns "undefined" if the thread naming functionality is not supported by the operating system.
std::optional<std::string> current_thread_name = get_current_thread_name();
if (current_thread_name && *current_thread_name != "slic3r_main")
throw CriticalException("Calling AppConfig::save() from a worker thread!"); throw CriticalException("Calling AppConfig::save() from a worker thread!");
}
// The config is first written to a file with a PID suffix and then moved // The config is first written to a file with a PID suffix and then moved
// to avoid race conditions with multiple instances of Slic3r // to avoid race conditions with multiple instances of Slic3r

View File

@ -191,6 +191,26 @@ std::optional<std::string> get_current_thread_name()
#endif // _WIN32 #endif // _WIN32
// To be called at the start of the application to save the current thread ID as the main (UI) thread ID.
static boost::thread::id g_main_thread_id;
void save_main_thread_id()
{
g_main_thread_id = boost::this_thread::get_id();
}
// Retrieve the cached main (UI) thread ID.
boost::thread::id get_main_thread_id()
{
return g_main_thread_id;
}
// Checks whether the main (UI) thread is active.
bool is_main_thread_active()
{
return get_main_thread_id() == boost::this_thread::get_id();
}
// Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID. // Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID.
// Also it sets locale of the worker threads to "C" for the G-code generator to produce "." as a decimal separator. // Also it sets locale of the worker threads to "C" for the G-code generator to produce "." as a decimal separator.
void name_tbb_thread_pool_threads_set_locale() void name_tbb_thread_pool_threads_set_locale()

View File

@ -29,6 +29,13 @@ inline bool set_thread_name(boost::thread &thread, const std::string &thread_nam
bool set_current_thread_name(const char *thread_name); bool set_current_thread_name(const char *thread_name);
inline bool set_current_thread_name(const std::string &thread_name) { return set_current_thread_name(thread_name.c_str()); } inline bool set_current_thread_name(const std::string &thread_name) { return set_current_thread_name(thread_name.c_str()); }
// To be called at the start of the application to save the current thread ID as the main (UI) thread ID.
void save_main_thread_id();
// Retrieve the cached main (UI) thread ID.
boost::thread::id get_main_thread_id();
// Checks whether the main (UI) thread is active.
bool is_main_thread_active();
// OSX specific: Set Quality of Service to "user initiated", so that the threads will be scheduled to high performance // OSX specific: Set Quality of Service to "user initiated", so that the threads will be scheduled to high performance
// cores if available. // cores if available.
void set_current_thread_qos(); void set_current_thread_qos();