2 workers.c -- worker threads
3 Copyright (C) 2006, 2007, 2008 Sebastian Freundt
5 Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 * This file is part of SXEmacs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of any contributors
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 /* Synched up with: Not in FSF. */
43 Lisp_Object Qworker_jobp;
44 Lisp_Object Qunknown, Qrunning, Qfinished, Qqueued;
49 eq_make_worker_scratch(eq_worker_t eqw, size_t size)
52 eq_worker_scratch(eqw) = xmalloc_atomic(size);
53 eq_worker_scratch_alloc_size(eqw) = size;
56 eq_worker_scratch(eqw) = NULL;
57 eq_worker_scratch_alloc_size(eqw) = 0;
65 eq_worker_t res = xnew_and_zero(struct eq_worker_s);
67 SXE_MUTEX_INIT(&eq_worker_mtx(res));
68 eq_worker_gcprolist(res) = NULL;
69 eq_make_worker_scratch(res, 0);
74 eq_free_worker_scratch(eq_worker_t eqw)
76 if (!eq_worker_scratch(eqw)) {
80 memset(eq_worker_scratch(eqw), 0, eq_worker_scratch_alloc_size(eqw));
81 xfree(eq_worker_scratch(eqw));
82 eq_worker_scratch(eqw) = NULL;
83 eq_worker_scratch_alloc_size(eqw) = 0;
88 eq_free_worker(eq_worker_t eqw)
93 SXE_MUTEX_FINI(&eq_worker_mtx(eqw));
94 eq_free_worker_scratch(eqw);
100 resize_worker_scratch(eq_worker_t eqw, size_t new_size)
103 eq_free_worker_scratch(eqw);
104 WORKERS_DEBUG_SCRATCH("resize to %ld\n", (long int)new_size);
105 eq_make_worker_scratch(eqw, new_size);
106 eq_unlock_meself(eqw);
111 /* worker jobs machinery */
113 init_worker_job_mtx(worker_job_t job)
115 SXE_MUTEX_INIT(&worker_job_mtx(job));
119 fini_worker_job_mtx(worker_job_t job)
121 SXE_MUTEX_FINI(&worker_job_mtx(job));
125 make_noseeum_worker_job(work_handler_t handler)
127 worker_job_t res = xnew(struct worker_job_s);
129 worker_job_queue(res) = Qnil;
130 worker_job_handler(res) = handler;
131 init_worker_job_mtx(res);
132 worker_job_result(res) = Qnil;
133 worker_job_plist(res) = Qnil;
138 make_worker_job(work_handler_t handler)
141 alloc_lcrecord_type(struct worker_job_s, &lrecord_worker_job);
143 worker_job_queue(res) = Qnil;
144 worker_job_handler(res) = handler;
145 worker_job_buffer(res) = NULL;
146 worker_job_buffer_alloc_size(res) = 0;
148 /* we have to care ourselves about mutex initialisation */
149 init_worker_job_mtx(res);
151 worker_job_state(res) = WORKER_JOB_UNKNOWN;
152 worker_job_result(res) = Qnil;
153 worker_job_plist(res) = Qnil;
158 make_worker_job_ts(Lisp_Object *into, work_handler_t handler)
162 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
165 job = make_worker_job(handler);
166 *into = (Lisp_Object)job;
167 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
174 worker_job_mark(Lisp_Object obj)
177 worker_job_t job = XWORKER_JOB(obj);
179 lock_worker_job(job);
180 if ((hdl = worker_job_handler(job)) &&
181 (work_handler_marker(hdl))) {
182 work_handler_marker(hdl)(job);
184 mark_object(worker_job_result(job));
185 mark_object(worker_job_plist(job));
186 unlock_worker_job(job);
187 return worker_job_queue(job);
191 worker_job_finalise(void *header, int SXE_UNUSED(for_disksave))
194 worker_job_t job = header;
195 if ((hdl = worker_job_handler(job)) &&
196 (work_handler_finaliser(hdl))) {
197 work_handler_finaliser(hdl)(job);
202 worker_job_print(Lisp_Object obj, Lisp_Object pcf, int escapeflag)
205 worker_job_t job = XWORKER_JOB(obj);
207 lock_worker_job(job);
208 write_c_string("#<worker-job", pcf);
209 if ((hdl = worker_job_handler(job)) &&
210 (work_handler_printer(hdl))) {
211 work_handler_printer(hdl)(job, pcf);
213 switch (worker_job_state(job)) {
214 case WORKER_JOB_QUEUED:
215 write_c_string(" :state 'queued>", pcf);
217 case WORKER_JOB_RUNNING:
218 write_c_string(" :state 'running>", pcf);
220 case WORKER_JOB_FINISHED:
221 write_c_string(" :state 'finished :result ", pcf);
222 print_internal(worker_job_result(job), pcf, escapeflag);
223 write_c_string(">", pcf);
225 case WORKER_JOB_UNKNOWN:
226 case NUMBER_OF_WORKER_JOB_STATES:
228 write_c_string(" :state 'unknown>", pcf);
231 unlock_worker_job(job);
235 worker_job_equal(Lisp_Object obj1, Lisp_Object obj2, int SXE_UNUSED(depth))
237 return (obj1 == obj2);
241 worker_job_hash (Lisp_Object obj, int SXE_UNUSED(depth))
243 return (unsigned long)obj;
247 worker_job_getprop(Lisp_Object obj, Lisp_Object property)
249 Lisp_Object result = Qnil;
250 worker_job_t job = XWORKER_JOB(obj);
252 lock_worker_job(job);
253 result = external_plist_get(
254 &worker_job_plist(job), property, 0, ERROR_ME);
255 unlock_worker_job(job);
260 worker_job_putprop(Lisp_Object obj, Lisp_Object property, Lisp_Object value)
262 worker_job_t job = XWORKER_JOB(obj);
264 lock_worker_job(job);
266 &worker_job_plist(job), property, value, 0, ERROR_ME);
267 unlock_worker_job(job);
272 worker_job_remprop(Lisp_Object obj, Lisp_Object property)
274 Lisp_Object result = Qnil;
275 worker_job_t job = XWORKER_JOB(obj);
277 lock_worker_job(job);
278 result = external_remprop(
279 &worker_job_plist(job), property, 0, ERROR_ME);
280 unlock_worker_job(job);
284 DEFUN("worker-job-plist", Fworker_job_plist, 1, 1, 0, /*
285 Return the property list of WORKER-JOB.
289 Lisp_Object result = Qnil;
292 CHECK_WORKER_JOB(worker_job);
293 job = XWORKER_JOB(worker_job);
295 lock_worker_job(job);
296 result = worker_job_plist(job);
297 unlock_worker_job(job);
301 static const struct lrecord_description worker_job_description[] = {
302 {XD_LISP_OBJECT, offsetof(struct worker_job_s, queue)},
303 {XD_OPAQUE_DATA_PTR, offsetof(struct worker_job_s, handler)},
304 {XD_OPAQUE_PTR, offsetof(struct worker_job_s, data)},
305 #if !defined(EF_USE_POM) && defined(HAVE_THREADS)
306 {XD_OPAQUE_PTR, offsetof(struct worker_job_s, mtx)},
308 {XD_LISP_OBJECT, offsetof(struct worker_job_s, result)},
309 {XD_LISP_OBJECT, offsetof(struct worker_job_s, plist)},
310 {XD_INT, offsetof(struct worker_job_s, state)},
312 {XD_OPAQUE_PTR, offsetof(struct worker_job_s, buffer)},
313 {XD_SIZE_T, offsetof(struct worker_job_s, buffer_alloc_size)},
318 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(
319 "worker_job", worker_job,
320 worker_job_mark, worker_job_print,
322 worker_job_equal, worker_job_hash,
323 worker_job_description,
324 worker_job_getprop, worker_job_putprop,
325 worker_job_remprop, Fworker_job_plist,
326 struct worker_job_s);
329 free_noseeum_worker_job(worker_job_t job)
331 worker_job_finalise(job, 0);
332 fini_worker_job_mtx(job);
337 DEFUN("get-worker-job-result", Fget_worker_job_result, 1, 1, 0, /*
338 Return the result slot of JOB.
344 CHECK_WORKER_JOB(job);
346 lock_worker_job(XWORKER_JOB(job));
347 res = XWORKER_JOB_RESULT(job);
348 unlock_worker_job(XWORKER_JOB(job));
352 DEFUN("worker-job-p", Fworker_job_p, 1, 1, 0, /*
353 Return non-nil iff JOB is a valid worker-job object.
357 if (WORKER_JOBP(job)) {
364 DEFUN("get-worker-job-state", Fget_worker_job_state, 1, 1, 0, /*
365 Return the state of JOB, will be one of
366 'unknown when the job is in an unknown state
367 'queued when the job is on the queue but not yet processed
368 'running when the job is currently processed
369 'finished when the job has finished
375 CHECK_WORKER_JOB(job);
377 lock_worker_job(XWORKER_JOB(job));
378 switch (XWORKER_JOB_STATE(job)) {
379 case WORKER_JOB_QUEUED:
382 case WORKER_JOB_RUNNING:
385 case WORKER_JOB_FINISHED:
388 case WORKER_JOB_UNKNOWN:
389 case NUMBER_OF_WORKER_JOB_STATES:
394 unlock_worker_job(XWORKER_JOB(job));
400 void syms_of_workers(void)
402 INIT_LRECORD_IMPLEMENTATION(worker_job);
404 DEFSUBR(Fget_worker_job_result);
405 DEFSUBR(Fget_worker_job_state);
406 DEFSUBR(Fworker_job_p);
407 DEFSUBR(Fworker_job_plist);
408 defsymbol(&Qworker_jobp, "worker-job-p");
412 DEFSYMBOL(Qfinished);
416 void vars_of_workers(void)
418 Fprovide(intern("workers"));
421 /* workers.c ends here */