promises.scm 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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. (lambda (x)
  47. (when (op-state-complete! state)
  48. (resume (lambda () x))))
  49. (lambda (err)
  50. (when (op-state-complete! state)
  51. (resume (lambda ()
  52. (raise-exception (promise-failure err)))))))
  53. (values))
  54. (make-base-operation #f try-fn block-fn))
  55. (define (await promise)
  56. ((perform-operation (await-promise-operation promise))))
  57. (define (call-with-async-result resolved rejected thunk)
  58. (with-exception-handler
  59. (lambda (err)
  60. (promise:complete! rejected err))
  61. (lambda ()
  62. (call-with-values thunk
  63. (lambda vals
  64. (promise:complete! resolved vals))))
  65. #:unwind? #t))