Partially sync files.el from XEmacs 21.5 for wildcard support.
[sxemacs] / src / events / workers.h
1 /*
2   workers.h -- worker threads
3   Copyright (C) 2006, 2007, 2008 Sebastian Freundt
4
5   Author:  Sebastian Freundt <hroptatyr@sxemacs.org>
6
7   * This file is part of SXEmacs.
8   *
9   * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   *
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.
19   *
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.
23   *
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.
35   */
36
37 /* Inspired by XEmacs' events.c written by Jamie Zawinski */
38
39 /* Synched up with: Not in FSF. */
40
41 #ifndef INCLUDED_workers_h_
42 #define INCLUDED_workers_h_
43
44 #include "semaphore.h"
45
46 #ifdef ALL_DEBUG_FLAGS
47 #undef WORKERS_DEBUG_FLAG
48 #define WORKERS_DEBUG_FLAG
49 #endif
50
51 #define __WORKERS_DEBUG__(args...)      fprintf(stderr, "workers " args)
52 #ifndef WORKERS_DEBUG_FLAG
53 #define WORKERS_DEBUG(args...)
54 #else
55 #define WORKERS_DEBUG(args...)          __WORKERS_DEBUG__(args)
56 #endif
57 #define WORKERS_DEBUG_WORKER(args...)   WORKERS_DEBUG("[worker]: " args)
58 #define WORKERS_DEBUG_SCRATCH(args...)  WORKERS_DEBUG("[scratch]: " args)
59 #define WORKERS_CRITICAL(args...)       __WORKERS_DEBUG__("CRITICAL: " args)
60
61 typedef struct eq_worker_s *eq_worker_t;
62 typedef struct worker_job_s *worker_job_t;
63 typedef struct work_handler_s *work_handler_t;
64 typedef enum worker_job_state_e worker_job_state_t;
65
66 extern Lisp_Object Qworker_jobp;
67 extern Lisp_Object Qunknown, Qrunning, Qfinished, Qqueued;
68
69 \f
70 struct eq_worker_s {
71         sxe_thread_t thread;
72         sxe_mutex_t mtx;
73         struct gcpro *gcprolist;
74
75         /* things that taste like ice cream */
76         void *scratch;
77         size_t scratch_alloc_size;
78 };
79
80 /* worker magic */
81 #define eq_worker_thread(_x)    ((_x)->thread)
82 #define eq_worker_mtx(_x)       ((_x)->mtx)
83 #define eq_worker_gcprolist(_x) ((_x)->gcprolist)
84 #define eq_worker_scratch(_x)   ((_x)->scratch)
85 #define eq_worker_scratch_alloc_size(_x)        ((_x)->scratch_alloc_size)
86
87 extern eq_worker_t eq_make_worker(void);
88 extern void eq_free_worker(eq_worker_t);
89 extern void resize_worker_scratch(eq_worker_t eqw, size_t new_size);
90
91 extern_inline void eq_lock_meself(eq_worker_t eqw);
92 extern_inline void eq_unlock_meself(eq_worker_t eqw);
93 extern_inline void lock_worker_job(worker_job_t job);
94 extern_inline void unlock_worker_job(worker_job_t job);
95
96 extern_inline void
97 eq_lock_meself(eq_worker_t eqw)
98 {
99         SXE_MUTEX_LOCK(&eq_worker_mtx(eqw));
100 }
101
102 extern_inline void
103 eq_unlock_meself(eq_worker_t eqw)
104 {
105         SXE_MUTEX_UNLOCK(&eq_worker_mtx(eqw));
106 }
107
108 \f
109 enum worker_job_state_e {
110         WORKER_JOB_UNKNOWN,
111         WORKER_JOB_QUEUED,
112         WORKER_JOB_RUNNING,
113         WORKER_JOB_FINISHED,
114         NUMBER_OF_WORKER_JOB_STATES
115 };
116
117 struct worker_job_s {
118         struct lcrecord_header lheader;
119         Lisp_Object queue;      /* used to be event_queue_t */
120         work_handler_t handler;
121         void *data;
122 #if !defined(EF_USE_POM) && defined(HAVE_THREADS)
123         sxe_mutex_t mtx;
124 #endif
125         worker_job_state_t state;
126
127         Lisp_Object result;
128         Lisp_Object plist;
129
130         /* some support from the underlying worker */
131         void *buffer;
132         size_t buffer_alloc_size;
133 };
134
135 DECLARE_LRECORD(worker_job, struct worker_job_s);
136 #define XWORKER_JOB(x)          XRECORD(x, worker_job, struct worker_job_s)
137 #define XSETWORKER_JOB(x, p)    XSETRECORD(x, p, worker_job)
138 #define wrap_worker_job(p)      wrap_object(p)
139 #define WORKER_JOBP(x)          RECORDP(x, worker_job)
140 #define CHECK_WORKER_JOB(x)     CHECK_RECORD(x, worker_job)
141 #define CONCHECK_WORKER_JOB(x)  CONCHECK_RECORD(x, worker_job)
142
143 #define worker_job_handler(_x)  ((_x)->handler)
144 #define worker_job_queue(_x)    ((_x)->queue)
145 #define worker_job_data(_x)     ((_x)->data)
146 #define worker_job_state(_x)    ((_x)->state)
147 #define worker_job_result(_x)   ((_x)->result)
148 #define worker_job_plist(_x)    ((_x)->plist)
149 #if defined(EF_USE_POM)
150 #define worker_job_mtx(_x)      (XRECORD_MTX(_x))
151 #else
152 #define worker_job_mtx(_x)      ((_x)->mtx)
153 #endif
154 #define worker_job_buffer(_x)   ((_x)->buffer)
155 #define worker_job_buffer_alloc_size(_x)        ((_x)->buffer_alloc_size)
156 #define XWORKER_JOB_HANDLER(_x) worker_job_handler(XWORKER_JOB(_x))
157 #define XWORKER_JOB_QUEUE(_x)   worker_job_queue(XWORKER_JOB(_x))
158 #define XWORKER_JOB_DATA(_x)    worker_job_data(XWORKER_JOB(_x))
159 #define XWORKER_JOB_STATE(_x)   worker_job_state(XWORKER_JOB(_x))
160 #define XWORKER_JOB_RESULT(_x)  worker_job_result(XWORKER_JOB(_x))
161 #define XWORKER_JOB_PLIST(x)    worker_job_plist(XWORKER_JOB(x))
162 #define XWORKER_JOB_MTX(_x)     worker_job_mtx(XWORKER_JOB(_x))
163 #define XWORKER_JOB_BUFFER(_x)  (worker_job_buffer(XWORKER_JOB(_x)))
164 #define XWORKER_JOB_BUFFER_ALLOC_SIZE(_x)       \
165         (worker_job_buffer_alloc_size(XWORKER_JOB(_x)))
166
167 extern worker_job_t make_noseeum_worker_job(work_handler_t handler);
168 extern void free_noseeum_worker_job(worker_job_t job);
169 extern worker_job_t make_worker_job(work_handler_t handler);
170 extern Lisp_Object make_worker_job_ts(Lisp_Object*, work_handler_t handler);
171
172 extern_inline void
173 lock_worker_job(worker_job_t job)
174 {
175         SXE_MUTEX_LOCK(&worker_job_mtx(job));
176 }
177
178 extern_inline void
179 unlock_worker_job(worker_job_t job)
180 {
181         SXE_MUTEX_UNLOCK(&worker_job_mtx(job));
182 }
183
184 \f
185 typedef void(*work_handler_mark_f)(worker_job_t);
186 typedef void(*work_handler_print_f)(worker_job_t, Lisp_Object pcf);
187 typedef void(*work_handler_finalise_f)(worker_job_t);
188 typedef void(*work_handler_f)(worker_job_t);
189 typedef void(*work_started_f)(worker_job_t);
190 typedef void(*work_finished_f)(worker_job_t);
191
192 struct work_handler_s {
193         work_handler_mark_f marker;
194         work_handler_print_f printer;
195         work_handler_finalise_f finaliser;
196         work_handler_f handler;
197         work_started_f started;
198         work_finished_f finished;
199 };
200
201 #define work_handler_marker(_x)         ((_x)->marker)
202 #define work_handler_printer(_x)        ((_x)->printer)
203 #define work_handler_finaliser(_x)      ((_x)->finaliser)
204 #define work_handler(_x)                ((_x)->handler)
205 #define work_started(_x)                ((_x)->started)
206 #define work_finished(_x)               ((_x)->finished)
207 #define work_handler_handle(_x, _y)     work_handler(_x)(_y)
208
209 #endif  /* INCLUDED_workers_h_ */