deque.scm 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. ;; Double-ended queue
  2. ;;;; Copyright (C) 2016 Andy Wingo <wingo@pobox.com>
  3. ;;;; Copyright (C) 2017 Christopher Allan Webber <cwebber@dustycloud.org>
  4. ;;;;
  5. ;;;; This library is free software; you can redistribute it and/or
  6. ;;;; modify it under the terms of the GNU Lesser General Public
  7. ;;;; License as published by the Free Software Foundation; either
  8. ;;;; version 3 of the License, or (at your option) any later version.
  9. ;;;;
  10. ;;;; This library is distributed in the hope that it will be useful,
  11. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. ;;;; Lesser General Public License for more details.
  14. ;;;;
  15. ;;;; You should have received a copy of the GNU Lesser General Public
  16. ;;;; License along with this library; if not, write to the Free Software
  17. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. (define-module (fibers deque)
  19. #:use-module (srfi srfi-9)
  20. #:use-module (ice-9 atomic)
  21. #:use-module (ice-9 match)
  22. #:export (make-deque
  23. make-empty-deque
  24. empty-deque?
  25. enqueue
  26. dequeue
  27. dequeue-all
  28. dequeue-match
  29. dequeue-filter
  30. undequeue
  31. dequeue!
  32. dequeue-all!
  33. enqueue!
  34. dequeue-filter!))
  35. ;; A functional double-ended queue ("deque") has a head and a tail,
  36. ;; which are both lists. The head is in FIFO order and the tail is in
  37. ;; LIFO order.
  38. (define-inlinable (make-deque head tail)
  39. (cons head tail))
  40. (define (make-empty-deque)
  41. (make-deque '() '()))
  42. (define (empty-deque? dq)
  43. (match dq
  44. ((() . ()) #t)
  45. (_ #f)))
  46. (define (enqueue dq item)
  47. (match dq
  48. ((head . tail)
  49. (make-deque head (cons item tail)))))
  50. ;; -> new deque, val | #f, #f
  51. (define (dequeue dq)
  52. (match dq
  53. ((() . ()) (values #f #f))
  54. ((() . tail)
  55. (dequeue (make-deque (reverse tail) '())))
  56. (((item . head) . tail)
  57. (values (make-deque head tail) item))))
  58. (define (dequeue-all dq)
  59. (match dq
  60. ((head . ()) head)
  61. ((head . tail) (append head (reverse tail)))))
  62. (define (dequeue-match dq pred)
  63. (match dq
  64. ((() . ()) (values #f #f))
  65. ((() . tail)
  66. (dequeue (make-deque (reverse tail) '())))
  67. (((item . head) . tail)
  68. (if (pred item)
  69. (values (make-deque head tail) item)
  70. (call-with-values (dequeue-match (make-deque head tail) pred)
  71. (lambda (dq item*)
  72. (values (undequeue dq item) item*)))))))
  73. (define (undequeue dq item)
  74. (match dq
  75. ((head . tail)
  76. (make-deque (cons item head) tail))))
  77. (define (dequeue-filter dq pred)
  78. (match dq
  79. ((head . tail)
  80. (cons (filter pred head)
  81. (filter pred tail)))))
  82. (define-inlinable (update! box f)
  83. (let spin ((x (atomic-box-ref box)))
  84. (call-with-values (lambda () (f x))
  85. (lambda (x* ret)
  86. (if (eq? x x*)
  87. ret
  88. (let ((x** (atomic-box-compare-and-swap! box x x*)))
  89. (if (eq? x x**)
  90. ret
  91. (spin x**))))))))
  92. (define* (dequeue! dqbox #:optional default)
  93. (update! dqbox (lambda (dq)
  94. (call-with-values (lambda () (dequeue dq))
  95. (lambda (dq* fiber)
  96. (if dq*
  97. (values dq* fiber)
  98. (values dq default)))))))
  99. (define (dequeue-all! dqbox)
  100. (update! dqbox (lambda (dq)
  101. (values (make-empty-deque)
  102. (dequeue-all dq)))))
  103. (define (enqueue! dqbox item)
  104. (update! dqbox (lambda (dq)
  105. (values (enqueue dq item)
  106. #f))))
  107. (define (dequeue-filter! dqbox pred)
  108. (update! dqbox (lambda (dq)
  109. (values (dequeue-filter dq pred)
  110. #f))))