This is a simple implementation of futures in JScheme. The construct (future X) immediately returns a future for the value of the expression X, and concurrently begins evaluating X in a separate thread. A future is initially undetermined. It becomes determined when its value has been computed. Use (touch f) to determine the value of a future, f. touch will suspend until the future is determined.
One issue is how to handle exceptions. In this version, a future becomes determined either by producing a value, or throwing an exception. A future catches any exception and rethrows it when it is touched.
Procedure names that begin with "%" are private.
} (define-macro (future exp) `(%make-future (lambda () ,exp))) (define (determined? f) ;; Is future f determined? (not (%future-thread f))) (define (future? f) ;; Is Object f a future? (and (vector? f) (eq? (vector-ref f 0) 'future))) (define (touch f) ;; If the future has a thread, it means it is not done. ;; Use join() to wait for it to be done before fetching the value. (let ((thread (%future-thread f))) (if thread (.join thread)) (if (%future-exception f) (throw (%future-exception f)) (%future-value f)))) ;;; `#(future ,thread ,value ,exception) (define (%allocate-future)(vector 'future #f #f #f)) (define (%future-thread f) (vector-ref f 1)) (define (%future-value f) (vector-ref f 2)) (define (%future-exception f) (vector-ref f 3)) (define (%future-result-set! f v e) (synchronize f (lambda (f) (vector-set! f 3 e) (vector-set! f 2 v) (vector-set! f 1 #f)))) (define (%make-future thunk) (let* ((fu (%allocate-future)) (thread (Thread. (lambda () (tryCatch (%future-result-set! fu (thunk) #f) (lambda (e) (%future-result-set! fu #f e))))))) (vector-set! fu 1 thread) (.start thread) fu))