external-event.scm 8.0 KB

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