| 45 | */ |
| 46 | template <class TFn, class... TArgs> |
| 47 | inline bool StartNewThread(std::thread *thr, std::string_view name, TFn&& _Fx, TArgs&&... _Ax) |
| 48 | { |
| 49 | try { |
| 50 | static std::mutex thread_startup_mutex; |
| 51 | std::lock_guard<std::mutex> lock(thread_startup_mutex); |
| 52 | |
| 53 | std::thread t([] (std::string name, TFn&& F, TArgs&&... A) { |
| 54 | /* Delay starting the thread till the main thread is finished |
| 55 | * with the administration. This prevent race-conditions on |
| 56 | * startup. */ |
| 57 | { |
| 58 | std::lock_guard<std::mutex> lock(thread_startup_mutex); |
| 59 | } |
| 60 | |
| 61 | SetCurrentThreadName(name); |
| 62 | CrashLog::InitThread(); |
| 63 | try { |
| 64 | /* Call user function with the given arguments. */ |
| 65 | F(A...); |
| 66 | } catch (std::exception &e) { |
| 67 | FatalError("Unhandled exception in {} thread: {}", name, e.what()); |
| 68 | } catch (...) { |
| 69 | NOT_REACHED(); |
| 70 | } |
| 71 | }, std::string{name}, std::forward<TFn>(_Fx), std::forward<TArgs>(_Ax)...); |
| 72 | |
| 73 | if (thr != nullptr) { |
| 74 | *thr = std::move(t); |
| 75 | } else { |
| 76 | t.detach(); |
| 77 | } |
| 78 | |
| 79 | return true; |
| 80 | } catch (const std::system_error &e) { |
| 81 | /* Something went wrong, the system we are running on might not support threads. */ |
| 82 | Debug(misc, 1, "Can't create thread '{}': {}", name, e.what()); |
| 83 | } |
| 84 | |
| 85 | return false; |
| 86 | } |
| 87 | |
| 88 | #endif /* THREAD_H */ |
no test coverage detected