void clear() { allKeys.clear(); allValues.clear(); }
VkBool32 VKTS_APIENTRY engineRun() { if (g_engineState != VKTS_ENGINE_INIT_STATE) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Not in initialize state."); return VK_FALSE; } if (engineGetNumberUpdateThreads() < VKTS_MIN_UPDATE_THREADS || engineGetNumberUpdateThreads() > VKTS_MAX_UPDATE_THREADS) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Number of update threads not correct."); return VK_FALSE; } // // Main thread gets all displays and windows attached. // const auto& displayList = _visualGetActiveDisplays(); for (size_t i = 0; i < displayList.size(); i++) { engineAttachDisplayToUpdateThread(displayList[i], g_allUpdateThreads[g_allUpdateThreads.size() - 1]); } const auto& windowList = _visualGetActiveWindows(); for (size_t i = 0; i < windowList.size(); i++) { engineAttachWindowToUpdateThread(windowList[i], g_allUpdateThreads[g_allUpdateThreads.size() - 1]); } // g_engineState = VKTS_ENGINE_UPDATE_STATE; logPrint(VKTS_LOG_INFO, "Engine: Started."); // Task queue creation. TaskQueueSP sendTaskQueue; TaskQueueSP executedTaskQueue; if (g_taskExecutorCount > 0) { sendTaskQueue = TaskQueueSP(new TaskQueue); if (!sendTaskQueue.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create task queue."); return VK_FALSE; } executedTaskQueue = TaskQueueSP(new TaskQueue); if (!executedTaskQueue.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create task queue."); return VK_FALSE; } } // Message dispatcher creation. MessageDispatcherSP messageDispatcher = MessageDispatcherSP(new MessageDispatcher()); if (!messageDispatcher.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create message dispatcher."); return VK_FALSE; } // Object, needed for synchronizing the executors. ExecutorSync executorSync; // // Task executor creation and launching, // SmartPointerVector<TaskExecutorSP> realTaskExecutors; SmartPointerVector<ThreadSP> realTaskThreads; for (uint32_t i = 0; i < g_taskExecutorCount; i++) { auto currentTaskExecutor = TaskExecutorSP(new TaskExecutor(i, executorSync, sendTaskQueue, executedTaskQueue)); if (!currentTaskExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current task executor."); return VK_FALSE; } auto currentRealThread = ThreadSP(new std::thread(&TaskExecutor::run, currentTaskExecutor)); if (!currentRealThread.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current real thread."); return VK_FALSE; } // realTaskExecutors.append(currentTaskExecutor); realTaskThreads.append(currentRealThread); logPrint(VKTS_LOG_INFO, "Engine: Task %d started.", currentTaskExecutor->getIndex()); } // // Update Thread creation and launching. // UpdateThreadExecutorSP mainUpdateThreadExecutor; SmartPointerVector<UpdateThreadExecutorSP> realUpdateThreadExecutors; SmartPointerVector<ThreadSP> realUpdateThreads; int32_t index = 0; for (size_t updateThreadIndex = 0; updateThreadIndex < g_allUpdateThreads.size(); updateThreadIndex++) { const auto& currentUpdateThread = g_allUpdateThreads[updateThreadIndex]; // const auto currentMessageDispatcher = (index == engineGetNumberUpdateThreads() - 1) ? messageDispatcher : MessageDispatcherSP(); // auto currentUpdateThreadContext = UpdateThreadContextSP(new UpdateThreadContext((int32_t) updateThreadIndex, (int32_t) g_allUpdateThreads.size(), g_tickTime, sendTaskQueue, executedTaskQueue)); if (!currentUpdateThreadContext.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create update thread context."); return VK_FALSE; } // for (auto currentDisplayWalker = g_allAttachedDisplays.lower_bound(currentUpdateThread); currentDisplayWalker != g_allAttachedDisplays.upper_bound(currentUpdateThread); currentDisplayWalker++) { currentUpdateThreadContext->attachDisplay(currentDisplayWalker->second); } // for (auto currentWindowWalker = g_allAttachedWindows.lower_bound(currentUpdateThread); currentWindowWalker != g_allAttachedWindows.upper_bound(currentUpdateThread); currentWindowWalker++) { currentUpdateThreadContext->attachWindow(currentWindowWalker->second); } // if (index == engineGetNumberUpdateThreads() - 1) { // Last thread is the main thread. mainUpdateThreadExecutor = UpdateThreadExecutorSP(new UpdateThreadExecutor(index, executorSync, currentUpdateThread, currentUpdateThreadContext, currentMessageDispatcher)); if (!mainUpdateThreadExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create main update thread executor."); return VK_FALSE; } } else { // Receive queue is the threads send queue. auto currentUpdateThreadExecutor = UpdateThreadExecutorSP(new UpdateThreadExecutor(index, executorSync, currentUpdateThread, currentUpdateThreadContext, currentMessageDispatcher)); if (!currentUpdateThreadExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current update thread executor."); return VK_FALSE; } realUpdateThreadExecutors.append(currentUpdateThreadExecutor); logPrint(VKTS_LOG_INFO, "Engine: Thread %d started.", currentUpdateThreadExecutor->getIndex()); auto currentRealThread = ThreadSP(new std::thread(&UpdateThreadExecutor::run, currentUpdateThreadExecutor)); if (!currentRealThread.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current real thread."); return VK_FALSE; } realUpdateThreads.append(currentRealThread); } index++; } // Run last thread and loop. logPrint(VKTS_LOG_INFO, "Engine: Thread %d started.", mainUpdateThreadExecutor->getIndex()); mainUpdateThreadExecutor->run(); // // Stopping everything. // logPrint(VKTS_LOG_INFO, "Engine: Thread %d stopped.", mainUpdateThreadExecutor->getIndex()); // Wait for all threads to finish in the reverse order they were created. for (auto reverseIndex = static_cast<int32_t>(realUpdateThreads.size()) - 1; reverseIndex >= 0; reverseIndex--) { const auto& currentRealThread = realUpdateThreads[reverseIndex]; currentRealThread->join(); logPrint(VKTS_LOG_INFO, "Engine: Thread %d stopped.", reverseIndex); } realUpdateThreadExecutors.clear(); realUpdateThreads.clear(); // if (sendTaskQueue.get()) { // Empty the queue. // As no update thread can feed the queue anymore, it is save to call reset. sendTaskQueue->reset(); // ITaskSP stopTask; logPrint(VKTS_LOG_SEVERE, "Engine: Disabling task queue."); for (uint32_t i = 0; i < g_taskExecutorCount; i++) { // Send an empty task to the queue, to exit the thread. sendTaskQueue->addTask(stopTask); } } // Wait for all tasks to finish in the reverse order they were created. for (auto reverseIndex = static_cast<int32_t>(realTaskThreads.size()) - 1; reverseIndex >= 0; reverseIndex--) { const auto& currentRealThread = realTaskThreads[reverseIndex]; currentRealThread->join(); logPrint(VKTS_LOG_INFO, "Engine: Task %d stopped.", reverseIndex); } realTaskExecutors.clear(); realTaskThreads.clear(); // g_engineState = VKTS_ENGINE_INIT_STATE; logPrint(VKTS_LOG_INFO, "Engine: Stopped."); return VK_TRUE; }