external-event.scm 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ;----------------
  3. ; External events
  4. (define (initialize-external-events!)
  5. (set-interrupt-handler! (enum interrupt external-event)
  6. external-event-handler))
  7. ; Exported procedure
  8. (define (waiting-for-external-events?)
  9. (zap-condvar-orphans!)
  10. (not (null? (external-event-condvars))))
  11. ;----------------
  12. ; A session slot contains an alist mapping external-event uids to
  13. ; condvars for external events on that uid. This works analogously to
  14. ; channels.
  15. (define external-events-wait-condvars-slot
  16. (make-session-data-slot! '()))
  17. (define (external-event-condvars)
  18. (session-data-ref external-events-wait-condvars-slot))
  19. (define (set-external-event-condvars! condvars)
  20. (session-data-set! external-events-wait-condvars-slot condvars))
  21. ; Adding a condvar and uid - the caller has already determined there
  22. ; is no existing condvar for this uid.
  23. (define (add-external-event-condvar! uid condvar)
  24. (set-external-event-condvars! (cons (cons uid condvar)
  25. (external-event-condvars))))
  26. (define (notify-external-event-condvar! condvar)
  27. (with-new-proposal (lose)
  28. (or (maybe-commit-and-set-condvar! condvar #t)
  29. (lose))))
  30. (define (external-event-handler uid enabled-interrupts)
  31. (cond
  32. ((fetch-external-event-condvar! uid)
  33. => notify-external-event-condvar!)))
  34. (define (wait-for-external-event uid)
  35. (let ((ints (disable-interrupts!))
  36. (condvar (make-condvar)))
  37. (add-external-event-condvar! uid condvar)
  38. (with-new-proposal (lose)
  39. (maybe-commit-and-wait-for-condvar condvar))
  40. (set-enabled-interrupts! ints)))
  41. ; This just deletes from the alist.
  42. (define (fetch-external-event-condvar! uid)
  43. (let ((condvars (external-event-condvars)))
  44. (cond ((null? condvars)
  45. #f)
  46. ((= uid (caar condvars))
  47. (set-external-event-condvars! (cdr condvars))
  48. (cdar condvars))
  49. (else
  50. (let loop ((condvars (cdr condvars)) (prev condvars))
  51. (cond ((null? condvars)
  52. #f)
  53. ((= uid (caar condvars))
  54. (set-cdr! prev (cdr condvars))
  55. (cdar condvars))
  56. (else
  57. (loop (cdr condvars) condvars))))))))
  58. ; Zap the condvars that no longer have waiters.
  59. (define (zap-condvar-orphans!)
  60. (with-interrupts-inhibited
  61. (lambda ()
  62. (let loop ((condvars (external-event-condvars)) (okay '()))
  63. (if (null? condvars)
  64. (set-external-event-condvars! okay)
  65. (let ((condvar (cdar condvars)))
  66. (loop (cdr condvars)
  67. (if (condvar-has-waiters? condvar)
  68. (cons (car condvars) okay)
  69. (begin
  70. (notify-external-event-condvar! condvar)
  71. okay)))))))))