external-event.scm 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Mike Sperber, Robert Ransom
  3. ;----------------
  4. ; External events
  5. (define (initialize-external-events!)
  6. (set-interrupt-handler! (enum interrupt external-event)
  7. external-event-handler))
  8. ;----------------
  9. ; A session slot contains an alist mapping external-event uids to
  10. ; condvars for external events on that uid. This works analogously to
  11. ; channels.
  12. (define external-events-wait-condvars-slot
  13. (make-session-data-slot! '()))
  14. (define (external-event-condvars)
  15. (session-data-ref external-events-wait-condvars-slot))
  16. (define (set-external-event-condvars! condvars)
  17. (session-data-set! external-events-wait-condvars-slot condvars))
  18. (define (add-external-event-condvar! uid condvar)
  19. (set-external-event-condvars! (cons (cons uid condvar)
  20. (external-event-condvars))))
  21. (define (notify-external-event-condvar! condvar)
  22. (with-new-proposal (lose)
  23. (or (maybe-commit-and-set-condvar! condvar #t)
  24. (lose))))
  25. (define (external-event-handler uid enabled-interrupts)
  26. (cond
  27. ((fetch-external-event-condvar! uid)
  28. => notify-external-event-condvar!)))
  29. ; the condvar will be set when the event occurs
  30. (define (register-condvar-for-external-event! uid condvar)
  31. (let ((ints (disable-interrupts!)))
  32. (add-external-event-condvar! uid condvar)
  33. (set-enabled-interrupts! ints)))
  34. ; make a new temporary event type and a condvar for it; return uid and condvar
  35. (define (new-external-event)
  36. (let ((event-uid (new-external-event-uid #f))
  37. (condvar (make-condvar)))
  38. (register-condvar-for-external-event! event-uid condvar)
  39. (values event-uid condvar)))
  40. ; actually wait for the event
  41. (define (wait-for-external-event condvar)
  42. (with-new-proposal (lose)
  43. (or (if (condvar-has-value? condvar)
  44. (maybe-commit)
  45. (maybe-commit-and-wait-for-condvar condvar #f))
  46. (lose))))
  47. ; This just deletes from the alist.
  48. (define (fetch-external-event-condvar! uid)
  49. (let ((condvars (external-event-condvars)))
  50. (cond ((null? condvars)
  51. #f)
  52. ((= uid (caar condvars))
  53. (set-external-event-condvars! (cdr condvars))
  54. (cdar condvars))
  55. (else
  56. (let loop ((condvars (cdr condvars)) (prev condvars))
  57. (cond ((null? condvars)
  58. #f)
  59. ((= uid (caar condvars))
  60. (set-cdr! prev (cdr condvars))
  61. (cdar condvars))
  62. (else
  63. (loop (cdr condvars) condvars))))))))
  64. ; Zap the condvars that no longer have waiters. This assumes disabled
  65. ; interrupts. The root scheduler typically calls this.
  66. (define (zap-external-event-orphans!)
  67. (let loop ((condvars (external-event-condvars)) (okay '()))
  68. (if (null? condvars)
  69. (set-external-event-condvars! okay)
  70. (let ((condvar (cdar condvars)))
  71. (loop (cdr condvars)
  72. (if (condvar-has-waiters? condvar)
  73. (cons (car condvars) okay)
  74. (begin
  75. (notify-external-event-condvar! condvar)
  76. okay)))))))