Coverage report: /home/ellis/comp/core/std/async.lisp
Kind | Covered | All | % |
expression | 0 | 102 | 0.0 |
branch | 0 | 12 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; async.lisp --- Aynchronous Functions
3
;; Futures, Promises, etc
14
speculation = future delay
16
;; NOTE: instead of 'force' we use 'await'
18
;; ref: https://github.com/lmj/lparallel
20
;; ref: https://doc.rust-lang.org/book/ch17-01-futures-and-syntax.html
23
(in-package :std/async)
25
(defconstant +no-result+ :null)
27
(defstruct (promise (:constructor promise))
28
"An placeholder object for a result which is not-yet-known."
32
(availablep t :type boolean))
35
"A promise which is fulfilled in parallel by evaluating the FN slot."
38
(canceledp nil :type boolean)
39
(fn nil :type (or null function)))
41
(defun fulfill-promise (obj fn)
42
(loop while (and (promise-availablep obj) (eq (promise-result obj) +no-result+))
43
do (with-mutex ((promise-lock obj) :wait-p nil)
45
(setf (promise-availablep obj) nil
47
(promise-result obj) (multiple-value-list (funcall fn)))
48
(setf (promise-availablep obj) t))
49
(when-let ((cvar (promise-cvar obj))) (condition-notify cvar))
52
(defun await-promise (obj)
53
(let ((res (promise-result obj))
54
(lock (promise-lock obj))
55
(cvar (promise-cvar obj)))
57
(setf cvar (sb-thread:make-waitqueue)))
58
(loop while (eq res +no-result+)
59
do (condition-wait cvar lock))
60
(condition-notify cvar)))
62
(defun fulfill-future (obj fn)
63
(when (eq (future-result obj) +no-result+)
64
(with-mutex ((future-lock obj) :wait-p nil)
65
;; task has been stolen from pool
66
(setf (future-canceledp obj) t)
68
(funcall fn (future-fn obj)))))
70
(defun await-future (obj)
71
;; task has been stolen from pool
72
(setf (future-canceledp obj) t)
74
(setf (future-result obj) (funcall (future-fn obj))
77
(defun fulfill (obj fn)
79
(promise (fulfill-promise obj fn))
80
(future (fulfill-future obj fn))))
84
(promise (promise-result obj))
85
(future (future-result obj))))
87
(defmacro future (&body body)
88
"Create a future which is fulfilled in parallel by the implicit progn BODY."
89
`(make-future :fn (lambda () ,@body)))
91
(defmacro while-waiting-for (obj &body body)
92
(with-gensyms (lock canceledp res)
93
`(let ((,lock (future-lock ,obj))
94
(,canceledp (future-canceledp ,obj))
95
(,res (future-result ,obj)))
96
(when (and (not ,canceledp)
97
(eq ,res +no-result+))
98
(with-mutex (,lock :wait-p nil)
101
(defun fulfilledp (obj)
103
(promise (not (eq (promise-result obj) +no-result+)))
104
(future (not (eq (future-result obj) +no-result+)))
107
(defun await (object)
110
(while-waiting-for object
112
(future (await-future object))
113
(promise (await-promise object))))