wind.scm 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. ; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
  2. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  3. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  4. ; This is file wind.scm. (Rhymes with "find," not "pinned.")
  5. ;;;; Dynamic-wind
  6. ; This is a version of dynamic-wind that tries to do "the right thing"
  7. ; in the presence of multiple threads of control.
  8. ; This definition of "the right thing" is due to Pavel Curtis, and is
  9. ; the one used in Scheme Xerox. It is very different from what you will
  10. ; find in, say, MIT Scheme.
  11. ;
  12. ; When we want to go to a new target state (e.g. on invoking a
  13. ; continuation), we ascend to the nearest common ancestor of the
  14. ; current state and the target state, executing the "out" (or
  15. ; "unwind") thunk for each state on the way; then we climb back down
  16. ; to the target state executing the "in" thunk for each state. Unlike
  17. ; the Hanson/Lamping algorithm, the tree of states is not altered in
  18. ; any way.
  19. ;
  20. ; Each thread starts out in the root state, but continuations capture
  21. ; the state where they're created.
  22. ; Dynamic-wind
  23. (define (dynamic-wind in body out)
  24. (in)
  25. (let ((here (get-dynamic-point)))
  26. (set-dynamic-point! (make-point (if here
  27. (+ (point-depth here) 1)
  28. 1)
  29. in
  30. out
  31. (get-dynamic-env)
  32. here))
  33. (let ((results (call-with-values body list)))
  34. (set-dynamic-point! here)
  35. (out)
  36. (apply values results))))
  37. ; call-with-current-continuation
  38. (define (call-with-current-continuation proc)
  39. (primitive-cwcc
  40. (lambda (cont)
  41. (let ((env (get-dynamic-env))
  42. (point (get-dynamic-point))
  43. (proposal (current-proposal)))
  44. ;; don't close over PROC
  45. (proc (continuation->procedure cont env point proposal))))))
  46. (define (continuation->procedure cont env point proposal)
  47. (lambda results
  48. (travel-to-point! (get-dynamic-point) point)
  49. (set-dynamic-env! env)
  50. (set-dynamic-point! point)
  51. (set-current-proposal! proposal)
  52. (with-continuation cont
  53. (lambda ()
  54. (apply values results)))))
  55. ; Point in state space = <depth, in, out, dynamic-env, parent>
  56. ; dynamic-env = dynamic environment for execution of the in and out thunks
  57. (define-record-type point :point
  58. (make-point depth in out dynamic-env parent)
  59. (depth point-depth)
  60. (in point-in)
  61. (out point-out)
  62. (dynamic-env point-dynamic-env)
  63. (parent point-parent))
  64. ; To make the modularity simpler, and to help Kali, the root point is #F.
  65. ; Go to a point in state space. This involves running out-thunks from
  66. ; the current point out to its common ancestor with the target, and
  67. ; then running in-thunks from the ancestor to the target.
  68. (define (travel-to-point! here target)
  69. (cond ((eq? here target) 'done)
  70. ((or (not here) ; HERE has reached the root.
  71. (and target
  72. (< (point-depth here)
  73. (point-depth target))))
  74. (travel-to-point! here (point-parent target))
  75. ((point-in target))
  76. (set-dynamic-env! (point-dynamic-env target))
  77. (set-dynamic-point! target))
  78. (else
  79. (set-dynamic-env! (point-dynamic-env here))
  80. (set-dynamic-point! here)
  81. ((point-out here))
  82. (travel-to-point! (point-parent here) target))))
  83. ; (put 'let-dynamic-point 'scheme-indent-hook 1)