waiter-queue.scm 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. ;;; Hoot implementation of Fibers
  2. ;;; Copyright (C) 2024 Igalia, S.L.
  3. ;;;
  4. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  5. ;;; you may not use this file except in compliance with the License.
  6. ;;; You may obtain a copy of the License at
  7. ;;;
  8. ;;; http://www.apache.org/licenses/LICENSE-2.0
  9. ;;;
  10. ;;; Unless required by applicable law or agreed to in writing, software
  11. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  12. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ;;; See the License for the specific language governing permissions and
  14. ;;; limitations under the License.
  15. (define-module (fibers waiter-queue)
  16. #:use-module (srfi srfi-9)
  17. #:use-module (ice-9 match)
  18. #:use-module (fibers operations)
  19. #:export (make-waiter-queue
  20. waiter-queue-push!
  21. waiter-queue-pop!
  22. waiter-queue-pop-all!))
  23. (define-record-type <waiter-queue>
  24. (%make-waiter-queue head)
  25. waiter-queue?
  26. (head waiter-queue-head set-waiter-queue-head!))
  27. (define (make-waiter-queue) (%make-waiter-queue '()))
  28. ;; Push an item on the back of the queue, removing any entries for
  29. ;; completed operations.
  30. (define (waiter-queue-push! q op-state data)
  31. (match q
  32. (($ <waiter-queue> head)
  33. (let ((new-tail (acons op-state data '())))
  34. (let drop-head ((head head))
  35. (match head
  36. (()
  37. ;; New tail is the only entry on the queue.
  38. (set-waiter-queue-head! q new-tail)
  39. (values))
  40. ((((? op-state-completed?) . _) . head*)
  41. ;; Queue head is completed already; pop it off.
  42. (drop-head head*))
  43. ((_ . tail)
  44. ;; Found a pending waiter on the queue. Filter out any
  45. ;; other completed operations and tack the new tail on the
  46. ;; back.
  47. (set-waiter-queue-head! q head)
  48. (let filter-tail ((prev head) (tail tail))
  49. (match tail
  50. (()
  51. (set-cdr! prev new-tail)
  52. (values))
  53. ((((? op-state-completed?) . _) . tail*)
  54. (set-cdr! prev tail*)
  55. (filter-tail prev tail*))
  56. ((_ . tail*)
  57. (filter-tail tail tail*)))))))))))
  58. (define* (waiter-queue-pop! q #:optional empty)
  59. (match (waiter-queue-head q)
  60. (() empty)
  61. (((op-state . data) . tail)
  62. (set-waiter-queue-head! q tail)
  63. (if (op-state-complete! op-state)
  64. data
  65. (waiter-queue-pop! q empty)))))
  66. (define (waiter-queue-pop-all! q proc)
  67. (let ((elts (waiter-queue-head q)))
  68. (set-waiter-queue-head! q '())
  69. (for-each (match-lambda
  70. ((op-state . data)
  71. (when (op-state-complete! op-state)
  72. (proc data))))
  73. elts)
  74. (values)))