| 143 | } |
| 144 | |
| 145 | void WindowSplash::createTask(const Task& task) { |
| 146 | auto runTask = [&, task] { |
| 147 | try { |
| 148 | // Save an iterator to the current task name |
| 149 | decltype(m_currTaskNames)::iterator taskNameIter; |
| 150 | { |
| 151 | std::lock_guard guard(m_progressMutex); |
| 152 | m_currTaskNames.push_back(task.name + "..."); |
| 153 | taskNameIter = std::prev(m_currTaskNames.end()); |
| 154 | } |
| 155 | |
| 156 | // When the task finished, increment the progress bar |
| 157 | ON_SCOPE_EXIT { |
| 158 | std::lock_guard guard(m_progressMutex); |
| 159 | m_completedTaskCount += 1; |
| 160 | m_progress = float(m_completedTaskCount) / float(m_totalTaskCount); |
| 161 | }; |
| 162 | |
| 163 | // Execute the actual task and track the amount of time it took to run |
| 164 | auto startTime = std::chrono::high_resolution_clock::now(); |
| 165 | bool taskStatus = task.callback(); |
| 166 | auto endTime = std::chrono::high_resolution_clock::now(); |
| 167 | |
| 168 | auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count(); |
| 169 | |
| 170 | if (taskStatus) |
| 171 | log::info("Task '{}' finished successfully in {} ms", task.name, milliseconds); |
| 172 | else |
| 173 | log::warn("Task '{}' finished unsuccessfully in {} ms", task.name, milliseconds); |
| 174 | |
| 175 | // Track the overall status of the tasks |
| 176 | m_taskStatus = m_taskStatus && taskStatus; |
| 177 | |
| 178 | // Erase the task name from the list of running tasks |
| 179 | { |
| 180 | std::lock_guard guard(m_progressMutex); |
| 181 | m_currTaskNames.erase(taskNameIter); |
| 182 | } |
| 183 | } catch (const std::exception &e) { |
| 184 | log::error("Init task '{}' threw an exception: {}", task.name, e.what()); |
| 185 | m_taskStatus = false; |
| 186 | } catch (...) { |
| 187 | log::error("Init task '{}' threw an unidentifiable exception", task.name); |
| 188 | m_taskStatus = false; |
| 189 | } |
| 190 | }; |
| 191 | |
| 192 | // If the task can be run asynchronously, run it in a separate thread |
| 193 | // otherwise run it in this thread and wait for it to finish |
| 194 | if (task.async) { |
| 195 | std::thread([name = task.name, runTask = std::move(runTask)] { |
| 196 | TaskManager::setCurrentThreadName(name); |
| 197 | runTask(); |
| 198 | }).detach(); |
| 199 | } else { |
| 200 | runTask(); |
| 201 | } |
| 202 | } |