add threadpool (WinUI3) newapi

Sun, 28 Jan 2024 20:46:49 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 28 Jan 2024 20:46:49 +0100
branch
newapi
changeset 235
9c79f00fbf36
parent 234
9036b346cd66
child 236
ee794586f51b

add threadpool (WinUI3)

make/vs/testapp/main.c file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
ui/winui/toolkit.cpp file | annotate | diff | comparison | revisions
ui/winui/toolkit.h file | annotate | diff | comparison | revisions
--- a/make/vs/testapp/main.c	Sun Jan 28 19:33:56 2024 +0100
+++ b/make/vs/testapp/main.c	Sun Jan 28 20:46:49 2024 +0100
@@ -185,6 +185,7 @@
 }
 
 
+
 void application_startup(UiEvent* event, void* data) {
     UiContext* gctx = ui_global_context();
     menuList = ui_list_new(gctx, "menulist");
--- a/ui/ui/toolkit.h	Sun Jan 28 19:33:56 2024 +0100
+++ b/ui/ui/toolkit.h	Sun Jan 28 20:46:49 2024 +0100
@@ -163,6 +163,8 @@
 typedef struct UiImage      UiImage;
 
 typedef struct UiDnD        UiDnD;
+
+typedef struct UiThreadpool UiThreadpool;
 /* end opaque types */
 
 typedef struct UiTabbedPane UiTabbedPane;
@@ -372,6 +374,9 @@
 
 UIEXPORT void ui_job(UiObject *obj, ui_threadfunc tf, void *td, ui_callback f, void *fd);
 UIEXPORT void ui_call_mainthread(ui_threadfunc tf, void* td);
+UIEXPORT UiThreadpool* ui_threadpool_create(int nthreads);
+UIEXPORT void ui_threadpool_destroy(UiThreadpool* pool);
+UIEXPORT void ui_threadpool_job(UiThreadpool* pool, UiObject* obj, ui_threadfunc tf, void* td, ui_callback f, void* fd);
 
 UIEXPORT void* ui_document_new(size_t size);
 UIEXPORT void  ui_document_destroy(void *doc);
--- 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);
+}
+
--- a/ui/winui/toolkit.h	Sun Jan 28 19:33:56 2024 +0100
+++ b/ui/winui/toolkit.h	Sun Jan 28 20:46:49 2024 +0100
@@ -30,6 +30,10 @@
 
 #include "../ui/toolkit.h"
 
+#include <queue>
+#include <mutex>
+#include <condition_variable>
+
 typedef struct UiJob {
     UiObject* obj;
     ui_threadfunc job_func;
@@ -38,6 +42,19 @@
     void* finish_data;
 } UiJob;
 
+struct UiThreadpool
+{
+	std::queue<UiJob*> queue;
+	std::mutex mutex;
+	std::condition_variable condition;
+
+	UiThreadpool(int nthreads);
+
+	void EnqueueJob(UiJob* job);
+
+	UiJob* GetJob();
+};
+
 typedef void(*ui_eventfunc)(void*, void*);
 
 void ui_app_run_startup();

mercurial