-
Notifications
You must be signed in to change notification settings - Fork 2
/
specials.lisp
136 lines (111 loc) · 3.89 KB
/
specials.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
(defpackage #:overlord/specials
(:use #:cl :overlord/types :alexandria :serapeum)
(:import-from :overlord/asdf
:asdf-system-version)
(:import-from #:lparallel
#:*task-priority*)
(:export #:*base*
#:*cli*
#:*db-version*
#:db-version
#:*suppress-phonies*
#:use-threads-p
#:*force*
#:worker-specials
#:register-worker-special
#:unregister-worker-special
#:register-worker-specials
#:unregister-worker-specials
#:wrap-worker-specials
#:*base-package*
#:base-package
#:*jobs*))
(in-package #:overlord/specials)
(defvar *worker-specials* '()
"List of special variables that should be propagated into worker threads.")
(defun worker-specials ()
*worker-specials*)
(defun (setf worker-specials) (value)
(check-type value list)
(assert (every #'symbolp value))
(assert (setp value))
(setf *worker-specials* value))
(defun register-worker-special (var)
"Register VAR as a variable that should be propagated into worker threads."
(check-type var symbol)
(pushnew var (worker-specials)))
(defun unregister-worker-special (var)
"Stop VAR from being propagated into worker threads."
(check-type var symbol)
(removef (worker-specials) var))
(defun register-worker-specials (vars)
"Register each var in VARS, as with `register-worker-special'."
(mapc #'register-worker-special vars))
(defun unregister-worker-specials (vars)
"Unregister each var in VARS as with `unregister-worker-special'."
(mapc #'unregister-worker-special vars))
(defun wrap-worker-specials (fn)
"Return a function suitable for passing to a worker that, that
lexically closes over the current dynamic value of every special that has been registered for propagation to worker threads."
(let* ((symbols (worker-specials))
(symbols (filter #'boundp symbols))
(values (mapcar #'symbol-value symbols)))
(assert (length= symbols values))
(lambda (&rest args)
(declare (dynamic-extent args))
(progv symbols values
(apply fn args)))))
(register-worker-specials
'(*package*
*readtable*
*read-base*
*read-eval*
*read-default-float-format*
*default-pathname-defaults*
*standard-output*
;; Propagating trace output makes debugging much easier.
*trace-output*
*error-output*
*task-priority*
;; Guard against someone trying to alter the list of worker
;; specials from within a worker.
*worker-specials*))
(defvar-unbound *base* "The current base.")
(register-worker-special '*base*)
(declaim (type (and directory-pathname absolute-pathname) *base*))
(defvar *cli* nil "Are we running on a CLI?")
(declaim (type boolean *cli*))
(defparameter *db-version*
(parse-integer
(asdf-system-version :overlord))
"Versioning for fasls.
Incrementing this should be sufficient to invalidate old fasls.")
(declaim (type db-version *db-version*))
(register-worker-special '*db-version*)
(defun db-version ()
(assure db-version *db-version*))
(defvar *use-threads* bt:*supports-threads-p*
"Whether to allow parallelism.")
(declaim (type boolean *use-threads*))
(defun use-threads-p ()
*use-threads*)
(defun (setf use-threads-p) (value)
(when value
(unless bt:*supports-threads-p*
(error "This Lisp implementation does not support threads.")))
(setf *use-threads* (true value)))
(defvar *suppress-phonies* nil)
(declaim (type boolean *suppress-phonies*))
(register-worker-special '*suppress-phonies*)
(defvar *force* nil
"Whether to force rebuilding.")
(register-worker-special '*force*)
(declaim (type package *base-package*))
(defvar-unbound *base-package*
"The package relative to which (if bound) the base should be computed.")
(-> base-package () package)
(defun base-package ()
(or (bound-value '*base-package*)
*package*))
(declaim (type (or null (integer 1 *)) jobs))
(defvar *jobs* nil)