add main event loop (Server)

Sat, 06 Dec 2025 15:24:13 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 06 Dec 2025 15:24:13 +0100
changeset 950
39641cf150eb
parent 949
ef8f13c8c08f
child 951
13cf4c932f21

add main event loop (Server)

ui/common/threadpool.c file | annotate | diff | comparison | revisions
ui/common/threadpool.h file | annotate | diff | comparison | revisions
ui/server/toolkit.c file | annotate | diff | comparison | revisions
ui/server/toolkit.h file | annotate | diff | comparison | revisions
--- a/ui/common/threadpool.c	Sat Dec 06 14:12:11 2025 +0100
+++ b/ui/common/threadpool.c	Sat Dec 06 15:24:13 2025 +0100
@@ -40,16 +40,11 @@
 
 UiThreadpool* threadpool_new(int min, int max) {
     UiThreadpool *pool = malloc(sizeof(UiThreadpool));
-    pool->queue = NULL;
-    pool->queue_len = 0;
+    pool->queue = ui_queue_create();
     pool->num_idle = 0;
     pool->min_threads = min;
     pool->max_threads = max;
 
-    pthread_mutex_init(&pool->queue_lock, NULL);
-    pthread_mutex_init(&pool->avlbl_lock, NULL);
-    pthread_cond_init(&pool->available, NULL);  
-
     return pool;
 }
 
@@ -93,69 +88,17 @@
 }
 
 threadpool_job* threadpool_get_job(UiThreadpool *pool) {
-    pthread_mutex_lock(&pool->queue_lock);
-
-    threadpool_job *job = NULL;
-    pool->num_idle++;
-    while(job == NULL) {
-        if(pool->queue_len == 0) {
-            pthread_cond_wait(&pool->available, &pool->queue_lock);
-            continue;
-        } else {
-            pool_queue_t *q = pool->queue;
-            job = q->job;
-            pool->queue = q->next;
-            pool->queue_len--;
-            free(q);
-        }
-    }
-    pool->num_idle--;
-
-    pthread_mutex_unlock(&pool->queue_lock);
+    threadpool_job *job = ui_queue_get_wait(pool->queue); 
     return job;
 }
 
-void threadpool_run(UiThreadpool *pool, job_callback_f func, void *data) {
-    // TODO: handle errors
-    
+void threadpool_run(UiThreadpool *pool, job_callback_f func, void *data) { 
     threadpool_job *job = malloc(sizeof(threadpool_job));
     job->callback = func;
     job->data = data;
-
-    pthread_mutex_lock(&pool->queue_lock);
-    threadpool_enqueue_job(pool, job);
-
-    int create_thread = 0;
-    int destroy_thread = 0;
-    int diff = pool->queue_len - pool->num_idle;
-    
-    //if(pool->queue_len == 1) {
-    pthread_cond_signal(&pool->available);
-    //}
-    
-    pthread_mutex_unlock(&pool->queue_lock);
+    ui_queue_put(pool->queue, job);
 }
 
-void threadpool_enqueue_job(UiThreadpool *pool, threadpool_job *job) {
-    pool_queue_t *q = malloc(sizeof(pool_queue_t));
-    q->job = job;
-    q->next = NULL;
-    
-    if(pool->queue == NULL) {
-        pool->queue = q;
-    } else {
-        pool_queue_t *last_elem = pool->queue;
-        while(last_elem->next != NULL) {
-            last_elem = last_elem->next;
-        }
-        last_elem->next = q;
-    }
-    pool->queue_len++;
-}
-
-
-
-
 
 
 UiThreadpool* ui_threadpool_create(int nthreads) {
@@ -202,6 +145,66 @@
     threadpool_run(pool, ui_threadpool_job_func, job);
 }
 
+/* --------------------------------- Queue --------------------------------- */
+
+UiQueue* ui_queue_create(void) {
+    UiQueue *queue = calloc(1, sizeof(UiQueue));
+    pthread_mutex_init(&queue->lock, NULL);
+    pthread_mutex_init(&queue->avlbl_lock, NULL);
+    pthread_cond_init(&queue->available, NULL);
+    return queue;
+}
+
+void ui_queue_free(UiQueue *queue) {
+    // TODO
+}
+
+void ui_queue_put(UiQueue *queue, void *data) {
+    // create queue element
+    UiQueueElm *elm = malloc(sizeof(UiQueueElm));
+    elm->data = data;
+    elm->next = NULL;
+    
+    pthread_mutex_lock(&queue->lock);
+    
+    // put queue element at the end of the linked list
+    if(queue->elements) {
+        UiQueueElm *end = queue->elements;
+        while(end->next) {
+            end = end->next;
+        }
+        end->next = elm;
+    } else {
+        queue->elements = elm;
+    }
+    queue->length++;
+    
+    // signal new available data
+    pthread_cond_signal(&queue->available);
+    
+    pthread_mutex_unlock(&queue->lock);
+}
+
+void* ui_queue_get_wait(UiQueue *queue) {
+    pthread_mutex_lock(&queue->lock);
+
+    void *data = NULL;
+    while(data == NULL) {
+        if(queue->length == 0) {
+            pthread_cond_wait(&queue->available, &queue->lock);
+            continue;
+        } else {
+            UiQueueElm *q = queue->elements;
+            data = q->data;
+            queue->elements = q->next;
+            queue->length--;
+            free(q);
+        }
+    }
+
+    pthread_mutex_unlock(&queue->lock);
+    return data;
+}
 
 #endif
 
--- a/ui/common/threadpool.h	Sat Dec 06 14:12:11 2025 +0100
+++ b/ui/common/threadpool.h	Sat Dec 06 15:24:13 2025 +0100
@@ -39,6 +39,8 @@
 extern "C" {
 #endif
     
+typedef struct UiQueueElm UiQueueElm;
+typedef struct UiQueue    UiQueue;
     
 typedef struct UiJob {
     UiObject      *obj;
@@ -48,22 +50,30 @@
     void          *finish_data;
 } UiJob;
     
+struct UiQueueElm {
+    void       *data;
+    UiQueueElm *next;
+};
+
+struct UiQueue {
+    UiQueueElm      *elements;
+    size_t          length;
+    pthread_mutex_t lock;
+    pthread_mutex_t avlbl_lock;
+    pthread_cond_t  available;
+};
     
 typedef struct  _threadpool_job   threadpool_job;
 typedef void*(*job_callback_f)(void *data);
     
 typedef struct _pool_queue pool_queue_t;
 struct UiThreadpool {
-    pthread_mutex_t queue_lock;
-    pthread_mutex_t avlbl_lock;
-    pthread_cond_t  available;
-    pool_queue_t    *queue;
-    uint32_t        queue_len;
-    uint32_t        num_idle;
-    int             min_threads;
-    int             max_threads;
-    pthread_t       *threads;
-    int             nthreads;
+    UiQueue   *queue;
+    uint32_t  num_idle;
+    int       min_threads;
+    int       max_threads;
+    pthread_t *threads;
+    int       nthreads;
 };
 
 struct _threadpool_job {
@@ -82,7 +92,11 @@
 void* threadpool_func(void *data);
 threadpool_job* threadpool_get_job(UiThreadpool *pool);
 void threadpool_run(UiThreadpool *pool, job_callback_f func, void *data);
-void threadpool_enqueue_job(UiThreadpool *pool, threadpool_job *job);
+
+UiQueue* ui_queue_create(void);
+void ui_queue_free(UiQueue *queue);
+void ui_queue_put(UiQueue *queue, void *data);
+void* ui_queue_get_wait(UiQueue *queue);
 
 #ifdef __cplusplus
 }
--- a/ui/server/toolkit.c	Sat Dec 06 14:12:11 2025 +0100
+++ b/ui/server/toolkit.c	Sat Dec 06 15:24:13 2025 +0100
@@ -33,4 +33,49 @@
 
 #include "toolkit.h"
 
+#include "../common/message.h"
+#include "../common/threadpool.h"
 
+static const char *ui_app_name;
+
+static UiMessageHandler *message_handler;
+
+static ui_callback onstartup;
+static void *onstartupdata;
+
+static UiQueue *event_queue;
+
+void ui_init(const char *appname, int argc, char **argv) {
+    ui_app_name = appname;
+    
+    message_handler = uic_simple_msg_handler(STDIN_FILENO, STDOUT_FILENO, ui_server_message_received);
+}
+
+const char* ui_appname() {
+    return ui_app_name;
+}
+
+void ui_onstartup(ui_callback f, void *userdata) {
+    onstartup = f;
+    onstartupdata = userdata;
+}
+
+void ui_add_styledata(const char *styledata, int len) {
+    // NOOP
+}
+
+
+void ui_server_message_received(cxstring msg) {
+    
+}
+
+void ui_main(void) {
+    event_queue = ui_queue_create();
+    UiServerEvent *event = NULL;
+    while((event = ui_queue_get_wait(event_queue)) != NULL) {
+        if(event->callback) {
+            event->callback(&event->event, event->userdata);
+        }
+    }
+    ui_queue_free(event_queue);
+}
--- a/ui/server/toolkit.h	Sat Dec 06 14:12:11 2025 +0100
+++ b/ui/server/toolkit.h	Sat Dec 06 15:24:13 2025 +0100
@@ -34,10 +34,29 @@
 #include "../common/context.h"
 #include "../common/object.h"
 
+#include <cx/string.h>
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
+    
+typedef struct UiServerEvent      UiServerEvent;
+typedef struct UiServerEventData  UiServerEventData;
+typedef void(*ui_srvevent_func)(UiServerEventData *event, void *userdata);
+    
+struct UiServerEventData {
+    UiObject *obj;
+    cxmutstr str;
+    int intvalue;
+};
 
+struct UiServerEvent {
+    UiServerEventData event;
+    ui_srvevent_func callback;
+    void *userdata;
+};
+
+void ui_server_message_received(cxstring msg);
 
 
 #ifdef	__cplusplus

mercurial