1 ;;;; Copyright (C) 1996, 1998, 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
3 ;;;; This library is free software; you can redistribute it and/or
4 ;;;; modify it under the terms of the GNU Lesser General Public
5 ;;;; License as published by the Free Software Foundation; either
6 ;;;; version 2.1 of the License, or (at your option) any later version.
8 ;;;; This library is distributed in the hope that it will be useful,
9 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 ;;;; Lesser General Public License for more details.
13 ;;;; You should have received a copy of the GNU Lesser General Public
14 ;;;; License along with this library; if not, write to the Free Software
15 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 ;;;; ----------------------------------------------------------------
18 ;;;; threads.scm -- User-level interface to Guile's thread system
19 ;;;; 4 March 1996, Anthony Green <green@cygnus.com>
20 ;;;; Modified 5 October 1996, MDJ <djurfeldt@nada.kth.se>
21 ;;;; Modified 6 April 2001, ttn
22 ;;;; ----------------------------------------------------------------
27 ;; This module is documented in the Guile Reference Manual.
28 ;; Briefly, one procedure is exported: `%thread-handler';
29 ;; as well as four macros: `make-thread', `begin-thread',
30 ;; `with-mutex' and `monitor'.
34 (define-module (ice-9 threads)
41 :export-syntax (begin-thread
50 (define (par-mapper mapper)
51 (lambda (proc . arglists)
55 (begin-thread (apply proc args)))
58 (define par-map (par-mapper map))
59 (define par-for-each (par-mapper for-each))
61 (define (n-par-map n proc . arglists)
62 (let* ((m (make-mutex))
64 (results (make-list (length (car arglists))))
68 (for-each join-thread threads)
76 (let ((args (map car arglists))
78 (set! arglists (map cdr arglists))
79 (set! result (cdr result))
81 (set-car! my-result (apply proc args))
85 (define (n-par-for-each n proc . arglists)
86 (let ((m (make-mutex))
90 (for-each join-thread threads))
95 (if (null? (car arglists))
97 (let ((args (map car arglists)))
98 (set! arglists (map cdr arglists))
104 ;;; The following procedure is motivated by the common and important
105 ;;; case where a lot of work should be done, (not too much) in parallel,
106 ;;; but the results need to be handled serially (for example when
107 ;;; writing them to a file).
109 (define (n-for-each-par-map n s-proc p-proc . arglists)
110 "Using N parallel processes, apply S-PROC in serial order on the results
111 of applying P-PROC on ARGLISTS."
112 (let* ((m (make-mutex))
114 (no-result '(no-value))
115 (results (make-list (length (car arglists)) no-result))
119 (for-each join-thread threads))
124 (cond ((null? results)
126 ((not (eq? (car results) no-result))
127 (let ((arg (car results)))
128 ;; stop others from choosing to process results
129 (set-car! results no-result)
133 (set! results (cdr results))
139 (let ((args (map car arglists))
141 (set! arglists (map cdr arglists))
142 (set! result (cdr result))
144 (set-car! my-result (apply p-proc args))
148 (define (thread-handler tag . args)
149 (fluid-set! the-last-stack #f)
150 (let ((n (length args))
151 (p (current-error-port)))
152 (display "In thread:" p)
164 (display "uncaught throw to " p)
171 ;;; Set system thread handler
172 (define %thread-handler thread-handler)
174 ; --- MACROS -------------------------------------------------------
176 (define-macro (begin-thread . forms)
179 `(call-with-new-thread
184 (define-macro (parallel . forms)
185 (cond ((null? forms) '(values))
186 ((null? (cdr forms)) (car forms))
188 (let ((vars (map (lambda (f)
192 (values ,@(map (lambda (v) `(join-thread ,v)) vars)))
193 ,@(map (lambda (form) `(begin-thread ,form)) forms))))))
195 (define-macro (letpar bindings . body)
196 (cond ((or (null? bindings) (null? (cdr bindings)))
197 `(let ,bindings ,@body))
199 (let ((vars (map car bindings)))
201 ((lambda ,vars ,@body)
202 ,@(map (lambda (v) `(join-thread ,v)) vars)))
203 ,@(map (lambda (b) `(begin-thread ,(cadr b))) bindings))))))
205 (define-macro (make-thread proc . args)
206 `(call-with-new-thread
211 (define-macro (with-mutex m . body)
213 (lambda () (lock-mutex ,m))
214 (lambda () (begin ,@body))
215 (lambda () (unlock-mutex ,m))))
217 (define-macro (monitor first . rest)
218 `(with-mutex ,(make-mutex)
222 ;;; threads.scm ends here