At the release of 1.0.1.
[python/dscho.git] / Modules / threadmodule.c
blob40169a3a4fa1e5e7d67ac910da3c44b39378dc57
1 /***********************************************************
2 Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Thread module */
26 /* Interface to Sjoerd's portable C thread library */
28 #include "allobjects.h"
29 #include "modsupport.h"
30 #include "ceval.h"
32 #include "thread.h"
34 int threads_started = 0;
36 static object *ThreadError;
39 /* Lock objects */
41 typedef struct {
42 OB_HEAD
43 type_lock lock_lock;
44 } lockobject;
46 extern typeobject Locktype; /* Really static, forward */
48 #define is_lockobject(v) ((v)->ob_type == &Locktype)
50 type_lock
51 getlocklock(lock)
52 object *lock;
54 if (lock == NULL || !is_lockobject(lock))
55 return NULL;
56 else
57 return ((lockobject *) lock)->lock_lock;
60 static lockobject *
61 newlockobject()
63 lockobject *self;
64 self = NEWOBJ(lockobject, &Locktype);
65 if (self == NULL)
66 return NULL;
67 self->lock_lock = allocate_lock();
68 if (self->lock_lock == NULL) {
69 DEL(self);
70 self = NULL;
71 err_setstr(ThreadError, "can't allocate lock");
73 return self;
76 static void
77 lock_dealloc(self)
78 lockobject *self;
80 /* Unlock the lock so it's safe to free it */
81 acquire_lock(self->lock_lock, 0);
82 release_lock(self->lock_lock);
84 free_lock(self->lock_lock);
85 DEL(self);
88 static object *
89 lock_acquire_lock(self, args)
90 lockobject *self;
91 object *args;
93 int i;
95 if (args != NULL) {
96 if (!getargs(args, "i", &i))
97 return NULL;
99 else
100 i = 1;
102 BGN_SAVE
103 i = acquire_lock(self->lock_lock, i);
104 END_SAVE
106 if (args == NULL) {
107 INCREF(None);
108 return None;
110 else
111 return newintobject((long)i);
114 static object *
115 lock_release_lock(self, args)
116 lockobject *self;
117 object *args;
119 if (!getnoarg(args))
120 return NULL;
122 /* Sanity check: the lock must be locked */
123 if (acquire_lock(self->lock_lock, 0)) {
124 release_lock(self->lock_lock);
125 err_setstr(ThreadError, "release unlocked lock");
126 return NULL;
129 release_lock(self->lock_lock);
130 INCREF(None);
131 return None;
134 static object *
135 lock_locked_lock(self, args)
136 lockobject *self;
137 object *args;
139 if (!getnoarg(args))
140 return NULL;
142 if (acquire_lock(self->lock_lock, 0)) {
143 release_lock(self->lock_lock);
144 return newintobject(0L);
146 return newintobject(1L);
149 static struct methodlist lock_methods[] = {
150 {"acquire_lock", lock_acquire_lock},
151 {"acquire", lock_acquire_lock},
152 {"release_lock", lock_release_lock},
153 {"release", lock_release_lock},
154 {"locked_lock", lock_locked_lock},
155 {"locked", lock_locked_lock},
156 {NULL, NULL} /* sentinel */
159 static object *
160 lock_getattr(self, name)
161 lockobject *self;
162 char *name;
164 return findmethod(lock_methods, (object *)self, name);
167 static typeobject Locktype = {
168 OB_HEAD_INIT(&Typetype)
169 0, /*ob_size*/
170 "lock", /*tp_name*/
171 sizeof(lockobject), /*tp_size*/
172 0, /*tp_itemsize*/
173 /* methods */
174 lock_dealloc, /*tp_dealloc*/
175 0, /*tp_print*/
176 lock_getattr, /*tp_getattr*/
177 0, /*tp_setattr*/
178 0, /*tp_compare*/
179 0, /*tp_repr*/
183 /* Module functions */
185 static void
186 t_bootstrap(args_raw)
187 void *args_raw;
189 object *args = (object *) args_raw;
190 object *func, *arg, *res;
192 threads_started++;
194 restore_thread((void *)NULL);
195 func = gettupleitem(args, 0);
196 arg = gettupleitem(args, 1);
197 res = call_object(func, arg);
198 DECREF(args); /* Matches the INCREF(args) in thread_start_new_thread */
199 if (res == NULL) {
200 fprintf(stderr, "Unhandled exception in thread:\n");
201 print_error(); /* From pythonmain.c */
203 (void) save_thread();
204 exit_thread();
207 static object *
208 thread_start_new_thread(self, args)
209 object *self; /* Not used */
210 object *args;
212 object *func, *arg;
214 if (!getargs(args, "(OO)", &func, &arg))
215 return NULL;
216 INCREF(args);
217 /* Initialize the interpreter's stack save/restore mechanism */
218 init_save_thread();
219 if (!start_new_thread(t_bootstrap, (void*) args)) {
220 DECREF(args);
221 err_setstr(ThreadError, "can't start new thread\n");
222 return NULL;
224 /* Otherwise the DECREF(args) is done by t_bootstrap */
225 INCREF(None);
226 return None;
229 static object *
230 thread_exit_thread(self, args)
231 object *self; /* Not used */
232 object *args;
234 if (!getnoarg(args))
235 return NULL;
236 (void) save_thread();
237 exit_thread();
238 for (;;) { } /* Should not be reached */
241 static object *
242 thread_exit_prog(self, args)
243 object *self; /* Not used */
244 object *args;
246 int sts;
247 if (!getargs(args, "i", &sts))
248 return NULL;
249 goaway(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
250 for (;;) { } /* Should not be reached */
253 static object *
254 thread_allocate_lock(self, args)
255 object *self; /* Not used */
256 object *args;
258 if (!getnoarg(args))
259 return NULL;
260 return (object *) newlockobject();
263 static struct methodlist thread_methods[] = {
264 {"start_new_thread", thread_start_new_thread},
265 {"start_new", thread_start_new_thread},
266 {"allocate_lock", thread_allocate_lock},
267 {"allocate", thread_allocate_lock},
268 {"exit_thread", thread_exit_thread},
269 {"exit", thread_exit_thread},
270 {"exit_prog", thread_exit_prog},
271 {NULL, NULL} /* sentinel */
275 /* Initialization function */
277 void
278 initthread()
280 object *m, *d, *x;
282 /* Create the module and add the functions */
283 m = initmodule("thread", thread_methods);
285 /* Add a symbolic constant */
286 d = getmoduledict(m);
287 ThreadError = newstringobject("thread.error");
288 INCREF(ThreadError);
289 dictinsert(d, "error", ThreadError);
291 /* Check for errors */
292 if (err_occurred())
293 fatal("can't initialize module thread");
295 /* Initialize the C thread library */
296 init_thread();