ui/common/threadpool.c

branch
newapi
changeset 280
e3565cf7c831
equal deleted inserted replaced
279:2ad83650d797 280:e3565cf7c831
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2024 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "threadpool.h"
30
31 #include <pthread.h>
32
33 #ifndef _WIN32
34
35
36 static threadpool_job kill_job;
37
38 UiThreadpool* threadpool_new(int min, int max) {
39 UiThreadpool *pool = malloc(sizeof(UiThreadpool));
40 pool->queue = NULL;
41 pool->queue_len = 0;
42 pool->num_idle = 0;
43 pool->min_threads = min;
44 pool->max_threads = max;
45
46 pthread_mutex_init(&pool->queue_lock, NULL);
47 pthread_mutex_init(&pool->avlbl_lock, NULL);
48 pthread_cond_init(&pool->available, NULL);
49
50 return pool;
51 }
52
53 int threadpool_start(UiThreadpool *pool) {
54 /* create pool threads */
55 for(int i=0;i<pool->min_threads;i++) {
56 pthread_t t;
57 if (pthread_create(&t, NULL, threadpool_func, pool) != 0) {
58 fprintf(stderr, "uic: threadpool_start: pthread_create failed: %s", strerror(errno));
59 return 1;
60 }
61 }
62 return 0;
63 }
64
65 void* threadpool_func(void *data) {
66 UiThreadpool *pool = (UiThreadpool*)data;
67
68 for(;;) {
69 threadpool_job *job = threadpool_get_job(pool);
70 if(job == &kill_job) {
71 break;
72 }
73
74 job->callback(job->data);
75
76 free(job);
77 }
78 return NULL;
79 }
80
81 threadpool_job* threadpool_get_job(UiThreadpool *pool) {
82 pthread_mutex_lock(&pool->queue_lock);
83
84 threadpool_job *job = NULL;
85 pool->num_idle++;
86 while(job == NULL) {
87 if(pool->queue_len == 0) {
88 pthread_cond_wait(&pool->available, &pool->queue_lock);
89 continue;
90 } else {
91 pool_queue_t *q = pool->queue;
92 job = q->job;
93 pool->queue = q->next;
94 pool->queue_len--;
95 free(q);
96 }
97 }
98 pool->num_idle--;
99
100 pthread_mutex_unlock(&pool->queue_lock);
101 return job;
102 }
103
104 void threadpool_run(UiThreadpool *pool, job_callback_f func, void *data) {
105 // TODO: handle errors
106
107 threadpool_job *job = malloc(sizeof(threadpool_job));
108 job->callback = func;
109 job->data = data;
110
111 pthread_mutex_lock(&pool->queue_lock);
112 threadpool_enqueue_job(pool, job);
113
114 int create_thread = 0;
115 int destroy_thread = 0;
116 int diff = pool->queue_len - pool->num_idle;
117
118 //if(pool->queue_len == 1) {
119 pthread_cond_signal(&pool->available);
120 //}
121
122 pthread_mutex_unlock(&pool->queue_lock);
123 }
124
125 void threadpool_enqueue_job(UiThreadpool *pool, threadpool_job *job) {
126 pool_queue_t *q = malloc(sizeof(pool_queue_t));
127 q->job = job;
128 q->next = NULL;
129
130 if(pool->queue == NULL) {
131 pool->queue = q;
132 } else {
133 pool_queue_t *last_elem = pool->queue;
134 while(last_elem->next != NULL) {
135 last_elem = last_elem->next;
136 }
137 last_elem->next = q;
138 }
139 pool->queue_len++;
140 }
141
142
143
144
145
146
147 UiThreadpool* ui_threadpool_create(int nthreads) {
148 return threadpool_new(nthreads, nthreads);
149 }
150
151 void ui_threadpool_destroy(UiThreadpool* pool) {
152
153 }
154
155 static void* ui_threadpool_job_func(void *data) {
156 UiJob *job = data;
157
158 free(job);
159 return NULL;
160 }
161
162 void ui_threadpool_job(UiThreadpool* pool, UiObject* obj, ui_threadfunc tf, void* td, ui_callback f, void* fd) {
163 UiJob* job = malloc(sizeof(UiJob));
164 job->obj = obj;
165 job->job_func = tf;
166 job->job_data = td;
167 job->finish_callback = f;
168 job->finish_data = fd;
169 threadpool_run(pool, ui_threadpool_job_func, job);
170 }
171
172
173 #endif
174

mercurial