1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #ifndef _WIN32
30
31 #include "threadpool.h"
32 #include "context.h"
33
34 #include <pthread.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <errno.h>
38
39 static threadpool_job kill_job;
40
41 UiThreadpool* threadpool_new(
int min,
int max) {
42 UiThreadpool *pool = malloc(
sizeof(UiThreadpool));
43 pool->queue = ui_queue_create();
44 pool->num_idle =
0;
45 pool->min_threads = min;
46 pool->max_threads = max;
47
48 return pool;
49 }
50
51 int threadpool_start(UiThreadpool *pool) {
52 pool->nthreads = pool->min_threads;
53 pool->threads = calloc(pool->max_threads,
sizeof(
pthread_t));
54
55 for(
int i=
0;i<pool->nthreads;i++) {
56 if (pthread_create(&pool->threads[i],
NULL, threadpool_func, pool) !=
0) {
57 fprintf(stderr,
"uic: threadpool_start: pthread_create failed: %s", strerror(errno));
58 return 1;
59 }
60 }
61 return 0;
62 }
63
64 int threadpool_join(UiThreadpool *pool) {
65 int err =
0;
66 for(
int i=
0;i<pool->nthreads;i++) {
67 if(pthread_join(pool->threads[i],
NULL)) {
68 err =
1;
69 }
70 }
71 return err;
72 }
73
74 void* threadpool_func(
void *data) {
75 UiThreadpool *pool = (UiThreadpool*)data;
76
77 for(;;) {
78 threadpool_job *job = threadpool_get_job(pool);
79 if(job == &kill_job) {
80 break;
81 }
82
83 job->callback(job->data);
84
85 free(job);
86 }
87 return NULL;
88 }
89
90 threadpool_job* threadpool_get_job(UiThreadpool *pool) {
91 threadpool_job *job = ui_queue_get_wait(pool->queue);
92 return job;
93 }
94
95 void threadpool_run(UiThreadpool *pool, job_callback_f func,
void *data) {
96 threadpool_job *job = malloc(
sizeof(threadpool_job));
97 job->callback = func;
98 job->data = data;
99 ui_queue_put(pool->queue, job);
100 }
101
102
103
104 UiThreadpool* ui_threadpool_create(
int nthreads) {
105 UiThreadpool *pool = threadpool_new(nthreads, nthreads);
106 threadpool_start(pool);
107 return pool;
108 }
109
110 void ui_threadpool_destroy(UiThreadpool* pool) {
111
112 }
113
114 static int ui_threadpool_job_finish(
void *data) {
115 UiJob *job = data;
116 UiEvent event;
117 event.obj = job->obj;
118 event.window = job->obj->window;
119 event.document = job->obj->ctx->document;
120 event.intval =
0;
121 event.eventdata =
NULL;
122 event.eventdatatype =
0;
123 job->finish_callback(&event, job->finish_data);
124 free(job);
125 return 0;
126 }
127
128 static void* ui_threadpool_job_func(
void *data) {
129 UiJob *job = data;
130 if (!job->job_func(job->job_data) && job->finish_callback) {
131 ui_call_mainthread(ui_threadpool_job_finish, job);
132 }
else {
133 free(job);
134 }
135 return NULL;
136 }
137
138 void ui_threadpool_job(UiThreadpool* pool, UiObject* obj, ui_threadfunc tf,
void* td, ui_callback f,
void* fd) {
139 UiJob* job = malloc(
sizeof(UiJob));
140 job->obj = obj;
141 job->job_func = tf;
142 job->job_data = td;
143 job->finish_callback = f;
144 job->finish_data = fd;
145 threadpool_run(pool, ui_threadpool_job_func, job);
146 }
147
148
149
150 UiQueue* ui_queue_create(
void) {
151 UiQueue *queue = calloc(
1,
sizeof(UiQueue));
152 pthread_mutex_init(&queue->lock,
NULL);
153 pthread_mutex_init(&queue->avlbl_lock,
NULL);
154 pthread_cond_init(&queue->available,
NULL);
155 return queue;
156 }
157
158 void ui_queue_free(UiQueue *queue) {
159
160
161 pthread_mutex_destroy(&queue->lock);
162 pthread_mutex_destroy(&queue->avlbl_lock);
163 pthread_cond_destroy(&queue->available);
164 free(queue);
165 }
166
167 void ui_queue_put(UiQueue *queue,
void *data) {
168
169 UiQueueElm *elm = malloc(
sizeof(UiQueueElm));
170 elm->data = data;
171 elm->next =
NULL;
172
173 pthread_mutex_lock(&queue->lock);
174
175
176 if(queue->elements) {
177 UiQueueElm *end = queue->elements;
178 while(end->next) {
179 end = end->next;
180 }
181 end->next = elm;
182 }
else {
183 queue->elements = elm;
184 }
185 queue->length++;
186
187
188 pthread_cond_signal(&queue->available);
189
190 pthread_mutex_unlock(&queue->lock);
191 }
192
193 void* ui_queue_get_wait(UiQueue *queue) {
194 pthread_mutex_lock(&queue->lock);
195
196 void *data =
NULL;
197 while(data ==
NULL) {
198 if(queue->length ==
0) {
199 pthread_cond_wait(&queue->available, &queue->lock);
200 continue;
201 }
else {
202 UiQueueElm *q = queue->elements;
203 data = q->data;
204 queue->elements = q->next;
205 queue->length--;
206 free(q);
207 }
208 }
209
210 pthread_mutex_unlock(&queue->lock);
211 return data;
212 }
213
214 #endif
215
216