promises.scm 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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 promises)
  16. #:use-module (fibers operations)
  17. #:use-module (hoot ffi)
  18. #:use-module ((hoot exceptions)
  19. #:select (make-exception-with-message
  20. make-exception-with-origin
  21. make-exception-with-irritants
  22. define-exception-type))
  23. #:export (await-promise-operation
  24. await
  25. call-with-async-result))
  26. (define-foreign promise:on-completed
  27. "rt" "promise_on_completed" (ref extern) (ref extern) (ref extern) -> none)
  28. (define-foreign promise:complete!
  29. "rt" "promise_complete" (ref extern) (ref eq) -> none)
  30. (define-exception-type &promise-failure &error
  31. make-promise-failure
  32. promise-failure?)
  33. (define (promise-failure val)
  34. (make-exception (make-promise-failure)
  35. (make-exception-with-message "promise was rejected")
  36. (make-exception-with-origin 'await-promise-operation)
  37. (make-exception-with-irritants (list val))))
  38. (define (await-promise-operation promise)
  39. "Make an operation that will complete when @var{promise} is resolved.
  40. Performing the operation produces one value: a thunk which when called
  41. will either return the value or throw an exception."
  42. (define (try-fn) #f)
  43. (define (block-fn state resume)
  44. (promise:on-completed
  45. promise
  46. (procedure->external
  47. (lambda (x)
  48. (when (op-state-complete! state)
  49. (resume (lambda () (lambda () x))))))
  50. (procedure->external
  51. (lambda (err)
  52. (when (op-state-complete! state)
  53. (resume (lambda ()
  54. (raise-exception (promise-failure err))))))))
  55. (values))
  56. (make-base-operation #f try-fn block-fn))
  57. (define (await promise)
  58. ((perform-operation (await-promise-operation promise))))
  59. (define (call-with-async-result resolved rejected thunk)
  60. (with-exception-handler
  61. (lambda (err)
  62. (promise:complete! rejected err))
  63. (lambda ()
  64. (call-with-values thunk
  65. (lambda vals
  66. (promise:complete! resolved vals))))
  67. #:unwind? #t))