ec3d05cfb914936123f7c0b8cd48c0050b0d6e4e
[strongswan.git] / Source / charon / thread_pool.c
1 /**
2 * @file thread_pool.c
3 *
4 * @brief Thread-pool with some threads processing the job_queue
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <stdlib.h>
24 #include <freeswan.h>
25 #include <pluto/constants.h>
26 #include <pluto/defs.h>
27 #include <pthread.h>
28
29 #include "allocator.h"
30 #include "thread_pool.h"
31 #include "job_queue.h"
32 #include "globals.h"
33
34 /**
35 * structure with private members for thread_pool
36 */
37 typedef struct {
38 /**
39 * inclusion of public members
40 */
41 thread_pool_t public;
42 /**
43 * number of running threads
44 */
45 size_t pool_size;
46 /**
47 * array of thread ids
48 */
49 pthread_t *threads;
50 } private_thread_pool_t;
51
52
53 static void job_processing(private_thread_pool_t *this)
54 {
55 /* cancellation disabled by default */
56 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
57
58 for (;;) {
59 job_t *job;
60
61 global_job_queue->get(global_job_queue, &job);
62
63 /* process them here */
64
65 job->destroy(job);
66 }
67
68 }
69
70 /**
71 * Implementation of thread_pool_t.get_pool_size
72 */
73 static status_t get_pool_size(private_thread_pool_t *this, size_t *size)
74 {
75 *size = this->pool_size;
76 return SUCCESS;
77 }
78
79 /**
80 * Implementation of thread_pool_t.destroy
81 */
82 static status_t destroy(private_thread_pool_t *this)
83 {
84 int current;
85 /* flag thread for termination */
86 for (current = 0; current < this->pool_size; current++) {
87 pthread_cancel(this->threads[current]);
88 }
89
90 /* wait for all threads */
91 for (current = 0; current < this->pool_size; current++) {
92 pthread_join(this->threads[current], NULL);
93 }
94
95 /* free mem */
96 allocator_free(this->threads);
97 allocator_free(this);
98 return SUCCESS;
99 }
100
101 /**
102 * Implementation of default constructor for thread_pool_t
103 */
104 thread_pool_t *thread_pool_create(size_t pool_size)
105 {
106 int current;
107
108 private_thread_pool_t *this = allocator_alloc_thing(private_thread_pool_t);
109
110 /* fill in public fields */
111 this->public.destroy = (status_t(*)(thread_pool_t*))destroy;
112 this->public.get_pool_size = (status_t(*)(thread_pool_t*, size_t*))get_pool_size;
113
114 this->pool_size = pool_size;
115 this->threads = allocator_alloc(sizeof(pthread_t) * pool_size);
116
117
118 /* try to create as many threads as possible, up tu pool_size */
119 for (current = 0; current < pool_size; current++) {
120 if (pthread_create(&(this->threads[current]), NULL, (void*(*)(void*))job_processing, this)) {
121 /* did we get any? */
122 if (current == 0) {
123
124 allocator_free(this->threads);
125 allocator_free(this);
126 return NULL;
127 }
128 /* not all threads could be created, but at least one :-/ */
129 this->pool_size = current;
130 return (thread_pool_t*)this;
131 }
132 }
133
134 return (thread_pool_t*)this;
135 }