-
Notifications
You must be signed in to change notification settings - Fork 0
/
ptpool.c
125 lines (90 loc) · 2.41 KB
/
ptpool.c
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// simple pthread pool
#include "ptpool.h"
struct pool_job {
void *(*routine)(void *);
void *arg;
};
struct pt_pool {
pthread_t *worker_threads;
struct pool_job *job_queue;
int head, tail;
size_t queue_size;
size_t max_threads;
size_t scheduled;
pthread_mutex_t mut;
pthread_cond_t to_work;
pthread_cond_t is_done;
};
struct job_args {
ptpool_t* pool;
struct pool_job td;
};
void *worker(void *pool_arg) {
ptpool_t *p = (ptpool_t*)pool_arg;
//printf("new worker is ready...\n");
while(1) {
struct pool_job job;
pthread_mutex_lock(&p->mut);
while(p->head == p->tail)
pthread_cond_wait(&p->to_work, &p->mut);
job = p->job_queue[p->head % p->queue_size];
p->head++;
p->scheduled++;
pthread_mutex_unlock(&p->mut);
job.routine(job.arg);
pthread_mutex_lock(&p->mut);
p->scheduled--;
if(p->scheduled == 0)
pthread_cond_signal(&p->is_done);
pthread_mutex_unlock(&p->mut);
}
return NULL;
}
ptpool_t *ptpool_create(size_t n, size_t qs) {
ptpool_t *p;
size_t i;
p = malloc(sizeof(ptpool_t));
p->max_threads = n;
p->scheduled = 0;
p->head = 0;
p->tail = 0;
p->queue_size = qs;
p->worker_threads = malloc(sizeof(pthread_t) * n);
p->job_queue = malloc(sizeof(struct pool_job) * qs);
pthread_mutex_init(&p->mut, NULL);
pthread_cond_init(&p->to_work, NULL);
pthread_cond_init(&p->is_done, NULL);
for (i = 0; i < n; i++) {
pthread_create(&p->worker_threads[i], NULL, worker, p);
}
return p;
}
void ptpool_destroy(ptpool_t *p) {
ptpool_wait(p);
for(int i = 0; i < p->max_threads; i++) {
pthread_detach(p->worker_threads[i]);
}
free(p->worker_threads);
free(p->job_queue);
free(p);
}
void ptpool_add_work(ptpool_t *p, void *(*func)(void*), void *arg) {
pthread_mutex_lock(&p->mut);
struct pool_job job;
if(p->head == p->tail) {
pthread_cond_broadcast(&p->to_work);
}
job.routine = func;
job.arg = arg;
p->job_queue[p->tail % p->queue_size] = job;
p->tail++;
pthread_mutex_unlock(&p->mut);
//printf("%d jobs is scheduled\n", p->tail);
}
void ptpool_wait(ptpool_t *p) {
pthread_mutex_lock(&p->mut);
while(p->scheduled > 0) {
pthread_cond_wait(&p->is_done, &p->mut);
}
pthread_mutex_unlock(&p->mut);
}