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