fluid.scm 3.1 KB

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