external-event.scm 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. ; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
  2. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  3. ; External events from C code
  4. ; Every type of external event gets a unique uid. We use the shared
  5. ; bindings to preserve them in the image.
  6. (define *number-of-event-types* 100)
  7. (define *event-types*)
  8. (define-record-type event-type :event-type
  9. (make-event-type uid used? next)
  10. (uid integer event-type-uid)
  11. (used? boolean event-type-used? set-event-type-used?!)
  12. ;; the pending external events form a queue, just like the channels
  13. (next event-type event-type-next set-event-type-next!))
  14. (define *pending-event-types-head*)
  15. (define *pending-event-types-tail*)
  16. (define *pending-event-types-ready*) ; last external event actually returned by event sysstem
  17. (define *unused-event-types-head*) ; unused types form a list, also linked by next
  18. (define (initialize-external-events)
  19. (set! *event-types* (make-vector *number-of-event-types* (null-pointer)))
  20. (if (null-pointer? *event-types*)
  21. (error "out of memory, unable to continue"))
  22. (let ((event-types-count *number-of-event-types*))
  23. (set! *number-of-event-types* 0)
  24. (set! *unused-event-types-head* (null-pointer))
  25. (if (not (add-external-event-types event-types-count))
  26. (error "out of memory, unable to continue")))
  27. (set! *pending-event-types-head* (null-pointer))
  28. (set! *pending-event-types-tail* (null-pointer))
  29. (set! *pending-event-types-ready* (null-pointer)))
  30. (define (add-external-event-types min-count)
  31. (let ((old-event-types *event-types*)
  32. (old-count *number-of-event-types*)
  33. (new-event-types (make-vector min-count (null-pointer))))
  34. (if (null-pointer? new-event-types)
  35. #f
  36. (let loop ((i 0))
  37. (cond
  38. ((= i min-count)
  39. (set! *event-types* new-event-types)
  40. (set! *number-of-event-types* min-count)
  41. (deallocate old-event-types)
  42. #t)
  43. ((< i old-count)
  44. (vector-set! new-event-types i
  45. (vector-ref old-event-types i))
  46. (goto loop (+ 1 i)))
  47. (else
  48. (let ((t (make-event-type i #f *unused-event-types-head*)))
  49. (if (null-pointer? t)
  50. (begin
  51. (set! *event-types* new-event-types)
  52. (set! *number-of-event-types* i)
  53. #f)
  54. (begin
  55. (vector-set! new-event-types i t)
  56. (set! *unused-event-types-head* t)
  57. (goto loop (+ 1 i)))))))))))
  58. (define (use-event-type-uid! id)
  59. (let ((type (vector-ref *event-types* id)))
  60. (if (event-type-used? type)
  61. (begin
  62. (write-error-string "trying to use an event uid that's already in use : ")
  63. (write-error-integer id)
  64. (write-error-newline)
  65. (error "assertion violation")))
  66. (set-event-type-used?! type #t)
  67. ;; delete from linked list
  68. (let loop ((previous (null-pointer))
  69. (unused-type *unused-event-types-head*)) ; usually, it should be the first
  70. (cond
  71. ((null-pointer? unused-type)
  72. (unspecific))
  73. ((not (eq? type unused-type))
  74. (loop unused-type (event-type-next unused-type)))
  75. ((null-pointer? previous)
  76. (set! *unused-event-types-head* (event-type-next unused-type)))
  77. (else
  78. (set-event-type-next! previous (event-type-next unused-type)))))
  79. (set-event-type-next! type (null-pointer))))
  80. (define (mark-event-type-uid-unused! uid)
  81. (let ((type (vector-ref *event-types* uid)))
  82. (cond
  83. ((not (null-pointer? (event-type-next type)))
  84. (write-error-string "trying to unregister external event that is still in use : ")
  85. (write-error-integer uid)
  86. (write-error-newline)
  87. (error "assertion violation"))
  88. (else
  89. (set-event-type-next! type *unused-event-types-head*)
  90. (set-event-type-used?! type #f)
  91. (set! *unused-event-types-head* type)))))
  92. ; returns -1 on out-of-memory
  93. (define (unused-event-type-uid)
  94. (cond
  95. ((not (null-pointer? *unused-event-types-head*))
  96. (event-type-uid *unused-event-types-head*))
  97. ((add-external-event-types (* 2 *number-of-event-types*))
  98. (unused-event-type-uid))
  99. (else -1)))
  100. (define (s48-external-event-uid)
  101. (let ((uid (unused-event-type-uid)))
  102. (if (= -1 uid)
  103. uid
  104. (begin
  105. (use-event-type-uid! uid)
  106. uid))))
  107. (define (s48-permanent-external-event-uid name)
  108. (let* ((binding (get-imported-binding name))
  109. (uid-val (shared-binding-ref binding)))
  110. (define (indeed uid)
  111. (shared-binding-set! binding (enter-fixnum uid))
  112. (use-event-type-uid! uid)
  113. uid)
  114. (if (fixnum? uid-val)
  115. (begin
  116. (let ((uid (extract-fixnum uid-val)))
  117. (cond
  118. ((< uid *number-of-event-types*)
  119. (indeed uid))
  120. ((add-external-event-types (+ 1 uid))
  121. (indeed uid))
  122. (else -1)))) ; out of memory
  123. (let ((uid (unused-event-type-uid)))
  124. (if (= -1 uid)
  125. uid
  126. (indeed uid))))))
  127. (define (s48-unregister-external-event-uid index)
  128. (define (lose/invalid)
  129. (write-error-string "trying to unregister invalid external event: ")
  130. (write-error-integer index)
  131. (write-error-newline)
  132. (error "assertion violation"))
  133. (if (>= index *number-of-event-types*)
  134. (lose/invalid))
  135. (let ((type (vector-ref *event-types* index)))
  136. (cond
  137. ((not (event-type-used? type))
  138. (lose/invalid))
  139. ((not (null-pointer? (event-type-next type)))
  140. (write-error-string "trying to unregister external event that is still in use : ")
  141. (write-error-integer index)
  142. (write-error-newline)
  143. (error "assertion violation"))
  144. (else
  145. (mark-event-type-uid-unused! index)))))
  146. ; Pending events
  147. ; This is intended to be called by the C code, but will generally
  148. ; need some sort of mutex protection there.
  149. (define (s48-external-event-ready?/unsafe)
  150. (not (null-pointer? *pending-event-types-ready*)))
  151. (define (s48-external-event-pending?/unsafe)
  152. (if (s48-external-event-ready?/unsafe)
  153. (begin
  154. (set! *pending-event-types-ready* (event-type-next *pending-event-types-ready*))
  155. #t)
  156. #f))
  157. (define (s48-note-external-event!/unsafe index)
  158. (define (lose)
  159. (write-error-string "invalid external event: ")
  160. (write-error-integer index)
  161. (write-error-newline)
  162. (error "assertion-violation"))
  163. (if (>= index *number-of-event-types*)
  164. (lose))
  165. (let ((type (vector-ref *event-types* index)))
  166. (cond
  167. ((not (event-type-used? type)) (lose))
  168. ((or (not (null-pointer? (event-type-next type))) ; already queued
  169. (eq? type *pending-event-types-head*) ; first and only
  170. (eq? type *pending-event-types-tail*)) ; last
  171. (unspecific))
  172. ((null-pointer? *pending-event-types-head*)
  173. (set! *pending-event-types-head* type)
  174. (set! *pending-event-types-tail* type)
  175. (set! *pending-event-types-ready* type))
  176. (else
  177. (set-event-type-next! *pending-event-types-tail* type)
  178. (set! *pending-event-types-tail* type)))))
  179. ; returns a uid and a boolean indicating whether more events are
  180. ; pending afterwards
  181. (define (s48-dequeue-external-event!/unsafe)
  182. (let* ((type *pending-event-types-head*)
  183. (next (event-type-next type)))
  184. (set! *pending-event-types-head* next)
  185. (set-event-type-next! type (null-pointer))
  186. (if (null-pointer? next)
  187. (set! *pending-event-types-tail* (null-pointer)))
  188. (values (event-type-uid type)
  189. (s48-external-event-ready?/unsafe))))