File: thread-env.scm

package info (click to toggle)
scsh-0.6 0.6.7-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 15,124 kB
  • ctags: 16,788
  • sloc: lisp: 82,839; ansic: 23,112; sh: 3,116; makefile: 829
file content (135 lines) | stat: -rw-r--r-- 3,979 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
; Copyright (c) 1993-2001 by Richard Kelsey and Jonathan Rees. See file COPYING.

; This is file fluid.scm.

; Fluid (dynamic) variables.

; Fluid variables are implemented using deep binding.  This allows
; each thread in a multiprocessor system to have its own fluid
; environment, and allows for fast thread switching in a multitasking
; one.

; CURRENT-THREAD and SET-CURRENT-THREAD! access a special virtual
; machine register.  On a multiprocessor, each processor would have
; its own current-thread register.  The run-time system stores the
; current thread in this register.

; Here we define a particular thread record, but a different one is
; defined by the (uniprocessor) threads package.  The current thread
; may actually be any kind of record as long as its first component
; can be used by the fluid variable implementation to maintain the
; deep-binding dynamic environment and its second component can be
; used by DYNAMIC-WIND.  This is kind of gross but it is motivated by
; efficiency concerns.

(define-record-type thread :thread
  (make-thread dynamic-env dynamic-point cell-env)
  (dynamic-env   thread-dynamic-env)
  (dynamic-point thread-dynamic-point)
  (cell-env      thread-cell-env))

(define (get-dynamic-env)
  (record-ref (current-thread) 1))

(define (set-dynamic-env! env)
  (record-set! (current-thread) 1 env))

; The dynamic-wind point used to be just an ordinary fluid variable, but that
; doesn't work well with threads.

(define (get-dynamic-point)
  (record-ref (current-thread) 2))

(define (set-dynamic-point! point)
  (record-set! (current-thread) 2 point))

;----------------
; Dynamic environment
; A dynamic environment is an alist where the cars are fluid records.

(define (with-dynamic-env env thunk)
  (let ((saved-env (get-dynamic-env)))
    (set-dynamic-env! env)
    (set! env #f)			;For GC and debugger
    (call-with-values
	;; thunk
	(let ((x thunk)) (set! thunk #f) x) ;For GC
      (lambda results
	(set-dynamic-env! saved-env)
	(apply values results)))))

(define (empty-dynamic-env) '())

; Each fluid has a top-level value that is used when the fluid is unbound
; in the current dynamic environment.

(define-record-type fluid :fluid
  (make-fluid top)
  (top fluid-top-level-value set-fluid-top-level-value!))

(define (fluid f)
  (let ((probe (assq f (get-dynamic-env))))
    (if probe (cdr probe) (fluid-top-level-value f))))

; Deprecated.

(define (set-fluid! f val)
  (let ((probe (assq f (get-dynamic-env))))
    (if probe (set-cdr! probe val) (set-fluid-top-level-value! f val))))

(define (let-fluid f val thunk)
  (with-dynamic-env (cons (cons f val) (get-dynamic-env)) thunk))

(define (let-fluids . args)
  (let loop ((args args)
	     (env (get-dynamic-env)))
    (if (null? (cdr args))
	(with-dynamic-env env (car args))
	(loop (cddr args)
	      (cons (cons (car args) (cadr args)) env)))))

; Handy utilities.

(define (fluid-cell-ref f)
  (cell-ref (fluid f)))

(define (fluid-cell-set! f value)
  (cell-set! (fluid f) value))

; Thread cells

(define-record-type thread-cell :thread-cell
  (make-thread-cell default)
  (default thread-cell-default))

(define (get-thread-cell-env)
  (record-ref (current-thread) 3))

(define (set-thread-cell-env! value)
  (record-set! (current-thread) 3 value))

(define (empty-thread-cell-env) '())

(define (thread-cell-ref thread-cell)
  (let ((probe (assq thread-cell (get-thread-cell-env))))
    (if probe
        (cdr probe)
        (thread-cell-default thread-cell))))

(define (thread-cell-set! thread-cell value)
  (let ((probe (assq thread-cell (get-thread-cell-env))))
    (if probe
        (set-cdr! probe value)
        (set-thread-cell-env! (cons (cons thread-cell
                                           value)
                                     (get-thread-cell-env))))))


; Initialize

(define (initialize-dynamic-state!)
  (set-current-thread!
   (make-thread (empty-dynamic-env) #f (empty-thread-cell-env))))

(initialize-dynamic-state!)