4 Copyright (C) Stefan Metzmacher 2016
6 ** NOTE! The following LGPL license applies to the tevent
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "system/filesys.h"
28 #include "tevent_internal.h"
29 #include "tevent_util.h"
30 #include "lib/util/dlinklist.h"
34 struct tevent_threadpool;
36 struct tevent_threadpool_job {
37 struct tevent_threadpool_job *prev, *next;
40 struct tevent_threadpool *pool;
41 struct tevent_req *req;
45 struct tevent_immediate *im;
51 const struct tevent_threadpool_job_description *desc;
56 struct tevent_threadpool {
57 struct tevent_threadpool *prev, *next;
58 struct tevent_context *ev;
61 struct tevent_threadpool_job *jobs;
62 struct tevent_queue *job_queue;
66 static int tevent_threadpool_destructor(struct tevent_threadpool *pool)
68 tevent_queue_stop(pool->job_queue);
70 //TODO DLIST_REMOVE all pool->jobs
75 struct tevent_threadpool *_tevent_threadpool_create(TALLOC_CTX *mem_ctx,
76 struct tevent_context *ev,
80 struct tevent_threadpool *pool;
82 if (ev->wrapper.glue != NULL) {
84 * stacking of wrappers is not supported
86 tevent_debug(ev->wrapper.glue->main_ev, TEVENT_DEBUG_FATAL,
87 "%s: %s() stacking not allowed",
93 pool = talloc_zero(mem_ctx, struct tevent_threadpool);
97 *pool = (struct tevent_threadpool) {
99 .max_threads = max_threads,
102 pool->job_queue = tevent_queue_create(pool, "job_queue");
103 if (pool->job_queue == NULL) {
108 DLIST_ADD_END(ev->threads.pools, pool);
110 talloc_set_destructor(pool, tevent_threadpool_destructor);
114 static int tevent_threadpool_job_destructor(struct tevent_threadpool_job *job)
116 if (job->busy.req != NULL) {
117 tevent_req_received(job->busy.req);
118 job->busy.req = NULL;
121 if (job->busy.pool != NULL) {
122 DLIST_REMOVE(job->busy.pool->jobs, job);
123 job->busy.pool = NULL;
129 struct tevent_threadpool_job *_tevent_threadpool_job_create(TALLOC_CTX *mem_ctx,
130 const struct tevent_threadpool_job_description *desc,
132 const char *location)
134 struct tevent_threadpool_job *job;
135 void **ppargs = (void **)pargs;
138 payload = sizeof(struct tevent_immediate) + desc->args_size;
139 if (payload < sizeof(struct tevent_immediate)) {
144 job = talloc_pooled_object(mem_ctx, struct tevent_threadpool_job,
150 *job = (struct tevent_threadpool_job) {
152 .im = tevent_create_immediate(job),
156 .args = talloc_zero_size(job, desc->args_size),
159 talloc_set_name_const(job->state.args, desc->args_type);
161 talloc_set_destructor(job, tevent_threadpool_job_destructor);
163 *ppargs = job->state.args;
167 struct tevent_threadpool_job_state {
168 struct tevent_threadpool_job *job;
171 static void tevent_threadpool_job_cleanup(struct tevent_req *req,
172 enum tevent_req_state req_state)
174 struct tevent_threadpool_job_state *state =
176 struct tevent_threadpool_job_state);
177 struct tevent_threadpool_job *job = state->job;
184 case TEVENT_REQ_RECEIVED:
192 job->busy.req = NULL;
195 struct tevent_req *tevent_threadpool_job_send(TALLOC_CTX *mem_ctx,
196 struct tevent_context *ev,
197 struct tevent_threadpool *pool,
198 struct tevent_threadpool_job *job)
200 struct tevent_req *req;
201 struct tevent_threadpool_job_state *state;
203 req = tevent_req_create(mem_ctx, &state,
204 struct tevent_threadpool_job_state);
210 tevent_req_set_cleanup_fn(req, tevent_threadpool_job_cleanup);
215 int tevent_threadpool_job_recv(struct tevent_req *req, int *perrno)
217 enum tevent_req_state req_state;
220 if (!tevent_req_is_error(req, &req_state, &error)) {
221 tevent_req_received(req);
226 case TEVENT_REQ_NO_MEMORY:
229 case TEVENT_REQ_TIMED_OUT:
232 case TEVENT_REQ_USER_ERROR:
233 *perrno = (int)error;
240 tevent_req_received(req);