fluid.scm 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees
  3. ; This is file fluid.scm.
  4. ; Fluid (dynamic) variables.
  5. ; Fluid variables are implemented using deep binding. This allows
  6. ; each thread in a multiprocessor system to have its own fluid
  7. ; environment, and allows for fast thread switching in a multitasking
  8. ; one.
  9. ; CURRENT-THREAD and SET-CURRENT-THREAD! access a special virtual
  10. ; machine register. On a multiprocessor, each processor would have
  11. ; its own current-thread register. The run-time system stores the
  12. ; current thread in this register.
  13. ; Here we define a particular thread record, but a different one is
  14. ; defined by the (uniprocessor) threads package. The current thread
  15. ; may actually be any kind of record as long as its first component
  16. ; can be used by the fluid variable implementation to maintain the
  17. ; deep-binding dynamic environment and its second component can be
  18. ; used by DYNAMIC-WIND. This is kind of gross but it is motivated by
  19. ; efficiency concerns.
  20. (define-record-type thread :thread
  21. (make-thread dynamic-env dynamic-point proposal)
  22. (dynamic-env thread-dynamic-env)
  23. (dynamic-point thread-dynamic-point)
  24. (proposal thread-proposal)) ; only accessed by the VM
  25. (define (get-dynamic-env)
  26. (record-ref (current-thread) 1))
  27. (define (set-dynamic-env! env)
  28. (record-set! (current-thread) 1 env))
  29. ; The dynamic-wind point used to be just an ordinary fluid variable, but that
  30. ; doesn't work well with threads.
  31. (define (get-dynamic-point)
  32. (record-ref (current-thread) 2))
  33. (define (set-dynamic-point! point)
  34. (record-set! (current-thread) 2 point))
  35. (define (initialize-dynamic-state!)
  36. (set-current-thread! (make-thread (empty-dynamic-env) #f #f)))
  37. ;----------------
  38. ; Dynamic environment
  39. ; A dynamic environment is an alist where the cars are fluid records.
  40. (define (with-dynamic-env env thunk)
  41. (let ((saved-env (get-dynamic-env)))
  42. (set-dynamic-env! env)
  43. (set! env #f) ;For GC and debugger
  44. (call-with-values
  45. ;; thunk
  46. (let ((x thunk)) (set! thunk #f) x) ;For GC
  47. (lambda results
  48. (set-dynamic-env! saved-env)
  49. (apply values results)))))
  50. (define (empty-dynamic-env) '())
  51. ; Each fluid has a top-level value that is used when the fluid is unbound
  52. ; in the current dynamic environment.
  53. (define-record-type fluid :fluid
  54. (make-fluid top)
  55. (top fluid-top-level-value set-fluid-top-level-value!))
  56. (define (fluid f)
  57. (let ((probe (assq f (get-dynamic-env))))
  58. (if probe (cdr probe) (fluid-top-level-value f))))
  59. ; Deprecated.
  60. (define (set-fluid! f val)
  61. (let ((probe (assq f (get-dynamic-env))))
  62. (if probe (set-cdr! probe val) (set-fluid-top-level-value! f val))))
  63. (define (let-fluid f val thunk)
  64. (with-dynamic-env (cons (cons f val) (get-dynamic-env)) thunk))
  65. (define (let-fluids . args)
  66. (let loop ((args args)
  67. (env (get-dynamic-env)))
  68. (if (null? (cdr args))
  69. (with-dynamic-env env (car args))
  70. (loop (cddr args)
  71. (cons (cons (car args) (cadr args)) env)))))
  72. ; Handy utilities.
  73. (define (fluid-cell-ref f)
  74. (cell-ref (fluid f)))
  75. (define (fluid-cell-set! f value)
  76. (cell-set! (fluid f) value))
  77. ; Initialize
  78. (initialize-dynamic-state!)