|
12 | 12 | mutex-acquire |
13 | 13 | mutex-release |
14 | 14 | call-with-new-thread |
15 | | - join-thread) |
| 15 | + join-thread |
| 16 | + &uncaught-exception |
| 17 | + uncaught-exception? |
| 18 | + uncaught-exception-reason |
| 19 | + &terminated-thread-exception |
| 20 | + terminated-thread-exception? |
| 21 | + terminated-thread-exception-thread) |
16 | 22 | (import (core primitives) |
17 | | - (core hashtables)) |
| 23 | + (core hashtables) |
| 24 | + (core conditions) |
| 25 | + (core records)) |
| 26 | + |
| 27 | + (define-condition-type &uncaught-exception &error |
| 28 | + make-uncaught-exception |
| 29 | + uncaught-exception? |
| 30 | + (reason uncaught-exception-reason)) |
| 31 | + |
| 32 | + (define-condition-type terminated-thread-exception &error |
| 33 | + make-terminated-thread-exception |
| 34 | + terminated-thread-exception? |
| 35 | + (thread terminated-thread-exception-thread)) |
| 36 | + |
| 37 | + (define-record-type uncaught |
| 38 | + (fields |
| 39 | + reason)) |
18 | 40 |
|
19 | 41 | ;; weak hashtable which keeps thread data until thread object is alive |
20 | 42 | (define %thread-results (make-weak-hashtable)) |
|
27 | 49 |
|
28 | 50 | (let ([t (fork-thread |
29 | 51 | (lambda () |
30 | | - (call-with-values |
31 | | - (lambda () |
32 | | - (with-mutex mutex |
33 | | - (set! thread (current-thread)) |
34 | | - (hashtable-set! %thread-join-data thread (cons cv mutex)) |
35 | | - (condition-signal cv)) |
36 | | - (with-exception-handler |
37 | | - (lambda (exn) exn) |
38 | | - thunk)) |
39 | | - (lambda vals |
40 | | - (with-mutex mutex |
41 | | - (hashtable-set! %thread-results cv vals) |
42 | | - (condition-broadcast cv))))))]) |
| 52 | + (call/cc |
| 53 | + (lambda (return) |
| 54 | + (call-with-values |
| 55 | + (lambda () |
| 56 | + (with-mutex mutex |
| 57 | + (set! thread (current-thread)) |
| 58 | + (hashtable-set! %thread-join-data thread (cons cv mutex)) |
| 59 | + (condition-signal cv)) |
| 60 | + (with-exception-handler |
| 61 | + (lambda (exn) |
| 62 | + (define obj (make-uncaught exn)) |
| 63 | + (with-mutex mutex |
| 64 | + (hashtable-set! %thread-results cv obj) |
| 65 | + (condition-broadcast cv)) |
| 66 | + (return #f)) |
| 67 | + thunk)) |
| 68 | + (lambda vals |
| 69 | + (with-mutex mutex |
| 70 | + (hashtable-set! %thread-results cv vals) |
| 71 | + (condition-broadcast cv))))))))]) |
43 | 72 |
|
44 | 73 | (with-mutex mutex |
45 | 74 | (let loop () |
|
51 | 80 | (loop)]))))) |
52 | 81 |
|
53 | 82 | (define (join-thread thread) |
| 83 | + "Wait for thread to terminate and return its values. If exception |
| 84 | + was raised in the thread, this function will raise &uncaught-exception |
| 85 | + with the original exception as reason." |
54 | 86 | (define data (hashtable-ref %thread-join-data thread #f)) |
55 | 87 |
|
56 | 88 | (unless data |
|
62 | 94 | (cond |
63 | 95 | [(hashtable-ref %thread-results cv #f) => |
64 | 96 | (lambda (res) |
| 97 | + (if (uncaught? res) |
| 98 | + (raise (make-uncaught-exception (uncaught-reason res)))) |
65 | 99 | (apply values res))] |
66 | 100 | [else |
67 | 101 | (condition-wait cv mutex) |
|
0 commit comments