diff options
Diffstat (limited to 'src/rw-lock.lisp')
| -rw-r--r-- | src/rw-lock.lisp | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/src/rw-lock.lisp b/src/rw-lock.lisp index 2a5e2c3..c0c545b 100644 --- a/src/rw-lock.lisp +++ b/src/rw-lock.lisp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | ;; These imports make this SBCL-dependent, but technically speaking we could live without them. | 8 | ;; These imports make this SBCL-dependent, but technically speaking we could live without them. |
| 9 | (:import-from :sb-sys | 9 | (:import-from :sb-sys |
| 10 | :allow-with-interrupts :with-local-interrupts :without-interrupts) | 10 | :allow-with-interrupts :with-local-interrupts :without-interrupts) |
| 11 | (:import-from :serapeum :->) | 11 | (:import-from :serapeum :-> :with-thunk) |
| 12 | (:import-from :ukkoclot/src/readtable :readtable) | 12 | (:import-from :ukkoclot/src/readtable :readtable) |
| 13 | (:export | 13 | (:export |
| 14 | #:rw-lock | 14 | #:rw-lock |
| @@ -16,9 +16,11 @@ | |||
| 16 | #:make-rw-lock | 16 | #:make-rw-lock |
| 17 | #:acquire-read-lock | 17 | #:acquire-read-lock |
| 18 | #:release-read-lock | 18 | #:release-read-lock |
| 19 | #:call-with-read-lock | ||
| 19 | #:with-read-lock | 20 | #:with-read-lock |
| 20 | #:acquire-write-lock | 21 | #:acquire-write-lock |
| 21 | #:release-write-lock | 22 | #:release-write-lock |
| 23 | #:call-with-write-lock | ||
| 22 | #:with-write-lock)) | 24 | #:with-write-lock)) |
| 23 | (in-package :ukkoclot/src/rw-lock) | 25 | (in-package :ukkoclot/src/rw-lock) |
| 24 | (in-readtable readtable) | 26 | (in-readtable readtable) |
| @@ -100,19 +102,24 @@ | |||
| 100 | (wakeup-waiters rw-lock)))) | 102 | (wakeup-waiters rw-lock)))) |
| 101 | rw-lock) | 103 | rw-lock) |
| 102 | 104 | ||
| 105 | (-> call-with-read-lock (rw-lock (function () t)) t) | ||
| 106 | (defun call-with-read-lock (rw-lock fn) | ||
| 107 | ;; TODO: timeout | ||
| 108 | "Similar to `with-read-lock', but instead of being a macro, it calls the function `fn'." | ||
| 109 | (let (lock-acquired) | ||
| 110 | (without-interrupts | ||
| 111 | (unwind-protect | ||
| 112 | (when (setf lock-acquired | ||
| 113 | (allow-with-interrupts (acquire-read-lock rw-lock))) | ||
| 114 | (with-local-interrupts (funcall fn))) | ||
| 115 | (when lock-acquired | ||
| 116 | (release-read-lock rw-lock)))))) | ||
| 117 | |||
| 103 | (defmacro with-read-lock ((rw-lock) &body body) | 118 | (defmacro with-read-lock ((rw-lock) &body body) |
| 104 | ;; TODO: timeout | 119 | ;; TODO: timeout |
| 105 | (with-gensyms (lock-acquired lock-value) | 120 | "Hold the read lock for the duration of the `body'." |
| 106 | `(let ((,lock-acquired) | 121 | (with-thunk (body) |
| 107 | (,lock-value ,rw-lock)) | 122 | `(call-with-read-lock ,rw-lock ,body))) |
| 108 | (without-interrupts | ||
| 109 | (unwind-protect | ||
| 110 | (when (setf ,lock-acquired | ||
| 111 | (allow-with-interrupts | ||
| 112 | (acquire-read-lock ,lock-value))) | ||
| 113 | (with-local-interrupts ,@body)) | ||
| 114 | (when ,lock-acquired | ||
| 115 | (release-read-lock ,lock-value))))))) | ||
| 116 | 123 | ||
| 117 | (-> acquire-write-lock (rw-lock &key (:wait boolean)) boolean) | 124 | (-> acquire-write-lock (rw-lock &key (:wait boolean)) boolean) |
| 118 | (defun acquire-write-lock (rw-lock &key (wait t)) | 125 | (defun acquire-write-lock (rw-lock &key (wait t)) |
| @@ -149,16 +156,21 @@ | |||
| 149 | (wakeup-waiters rw-lock))) | 156 | (wakeup-waiters rw-lock))) |
| 150 | rw-lock) | 157 | rw-lock) |
| 151 | 158 | ||
| 159 | (-> call-with-write-lock (rw-lock (function () t)) t) | ||
| 160 | (defun call-with-write-lock (rw-lock fn) | ||
| 161 | ;; TODO: timeout | ||
| 162 | "Similar to `with-write-lock', but instead of being a macro, it calls the function `fn'." | ||
| 163 | (let (lock-acquired) | ||
| 164 | (without-interrupts | ||
| 165 | (unwind-protect | ||
| 166 | (when (setf lock-acquired | ||
| 167 | (allow-with-interrupts (acquire-write-lock rw-lock))) | ||
| 168 | (with-local-interrupts (funcall fn))) | ||
| 169 | (when lock-acquired | ||
| 170 | (release-write-lock rw-lock)))))) | ||
| 171 | |||
| 152 | (defmacro with-write-lock ((rw-lock) &body body) | 172 | (defmacro with-write-lock ((rw-lock) &body body) |
| 153 | ;; TODO: timeout | 173 | ;; TODO: timeout |
| 154 | (with-gensyms (lock-acquired lock-value) | 174 | "Hold the write lock for the duration of the `body'." |
| 155 | `(let ((,lock-acquired) | 175 | (with-thunk (body) |
| 156 | (,lock-value ,rw-lock)) | 176 | `(call-with-write-lock ,rw-lock ,body))) |
| 157 | (without-interrupts | ||
| 158 | (unwind-protect | ||
| 159 | (when (setf ,lock-acquired | ||
| 160 | (allow-with-interrupts | ||
| 161 | (acquire-write-lock ,lock-value))) | ||
| 162 | (with-local-interrupts ,@body)) | ||
| 163 | (when ,lock-acquired | ||
| 164 | (release-write-lock ,lock-value))))))) | ||