url-future.el 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. ;;; url-future.el --- general futures facility for url.el
  2. ;; Copyright (C) 2011-2012 Free Software Foundation, Inc.
  3. ;; Author: Teodor Zlatanov <tzz@lifelogs.com>
  4. ;; Keywords: data
  5. ;; This file is part of GNU Emacs.
  6. ;;
  7. ;; GNU Emacs is free software: you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation, either version 3 of the License, or
  10. ;; (at your option) any later version.
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;; GNU General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;; Make a url-future (basically a defstruct):
  19. ;; (make-url-future :value (lambda () (calculation goes here))
  20. ;; :callback (lambda (future) (use future on success))
  21. ;; :errorback (lambda (future &rest error) (error handler)))
  22. ;; Then either call it with `url-future-call' or cancel it with
  23. ;; `url-future-cancel'. Generally the functions will return the
  24. ;; future itself, not the value it holds. Also the functions will
  25. ;; throw a url-future-already-done error if you try to call or cancel
  26. ;; a future more than once.
  27. ;; So, to get the value:
  28. ;; (when (url-future-completed-p future) (url-future-value future))
  29. ;; See `url-future-tests' and the code below for further details.
  30. ;;; Code:
  31. (eval-when-compile (require 'cl))
  32. (defstruct url-future callback errorback status value)
  33. (defmacro url-future-done-p (url-future)
  34. `(url-future-status ,url-future))
  35. (defmacro url-future-completed-p (url-future)
  36. `(eq (url-future-status ,url-future) t))
  37. (defmacro url-future-errored-p (url-future)
  38. `(eq (url-future-status ,url-future) 'error))
  39. (defmacro url-future-cancelled-p (url-future)
  40. `(eq (url-future-status ,url-future) 'cancel))
  41. (defun url-future-finish (url-future &optional status)
  42. (if (url-future-done-p url-future)
  43. (signal 'error 'url-future-already-done)
  44. (setf (url-future-status url-future) (or status t))
  45. ;; the status must be such that the future was completed
  46. ;; to run the callback
  47. (when (url-future-completed-p url-future)
  48. (funcall (or (url-future-callback url-future) 'ignore)
  49. url-future))
  50. url-future))
  51. (defun url-future-errored (url-future errorcons)
  52. (if (url-future-done-p url-future)
  53. (signal 'error 'url-future-already-done)
  54. (setf (url-future-status url-future) 'error)
  55. (setf (url-future-value url-future) errorcons)
  56. (funcall (or (url-future-errorback url-future) 'ignore)
  57. url-future errorcons)))
  58. (defun url-future-call (url-future)
  59. (if (url-future-done-p url-future)
  60. (signal 'error 'url-future-already-done)
  61. (let ((ff (url-future-value url-future)))
  62. (when (functionp ff)
  63. (condition-case catcher
  64. (setf (url-future-value url-future)
  65. (funcall ff))
  66. (error (url-future-errored url-future catcher)))
  67. (url-future-value url-future)))
  68. (if (url-future-errored-p url-future)
  69. url-future
  70. (url-future-finish url-future))))
  71. (defun url-future-cancel (url-future)
  72. (if (url-future-done-p url-future)
  73. (signal 'error 'url-future-already-done)
  74. (url-future-finish url-future 'cancel)))
  75. (provide 'url-future)
  76. ;;; url-future.el ends here