--- a/ui/winui/toolkit.cpp Sun Jan 28 19:33:56 2024 +0100 +++ b/ui/winui/toolkit.cpp Sun Jan 28 20:46:49 2024 +0100 @@ -43,8 +43,6 @@ #include "App.xaml.h" -#include <thread> - using namespace winrt; using namespace Microsoft::UI::Xaml; using namespace Microsoft::UI::Xaml::Controls; @@ -251,7 +249,7 @@ } static void ui_job_thread(UiJob* job) { - if (!job->job_func(job->job_data)) { + if (!job->job_func(job->job_data) && job->finish_callback) { bool isQueued = uiDispatcherQueue.TryEnqueue([job]() { UiEvent event; @@ -295,3 +293,70 @@ exit(-1); } } + +static UiJob kill_job; // &kill_job indicates to stop the thread + +static void ui_threadpool_run(UiThreadpool* pool) { + for (;;) { + UiJob* job = pool->GetJob(); + if (job == &kill_job) { + return; + } + else if (job) { + ui_job_thread(job); + } + } +} + +UiThreadpool::UiThreadpool(int nthreads) { + for (int i = 0; i < nthreads; i++) { + std::thread thread(ui_threadpool_run, this); + thread.detach(); + } +} + +void UiThreadpool::EnqueueJob(UiJob* job) +{ + std::unique_lock<std::mutex> lock(mutex); + queue.push(job); + lock.unlock(); + condition.notify_one(); +} + +UiJob* UiThreadpool::GetJob() { + std::unique_lock<std::mutex> lock(mutex); + + UiJob* job = nullptr; + while (!job) { + if (queue.empty()) { + condition.wait(lock); + continue; + } + else + { + job = queue.front(); + queue.pop(); + } + } + + return job; +} + +UIEXPORT UiThreadpool* ui_threadpool_create(int nthreads) { + return new UiThreadpool(nthreads); +} + +UIEXPORT void ui_threadpool_destroy(UiThreadpool* pool) { + // TODO +} + +UIEXPORT void ui_threadpool_job(UiThreadpool* pool, UiObject* obj, ui_threadfunc tf, void* td, ui_callback f, void* fd) { + UiJob* job = new UiJob; + job->obj = obj; + job->job_func = tf; + job->job_data = td; + job->finish_callback = f; + job->finish_data = fd; + pool->EnqueueJob(job); +} +