| 1 | ;;;-*- Mode: Lisp; Package: (WOOD) -*-
|
|---|
| 2 |
|
|---|
| 3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|---|
| 4 | ;;
|
|---|
| 5 | ;; persistent-clos.lisp
|
|---|
| 6 | ;; Support for saving/restoring CLOS instances to/from Wood persistent heaps.
|
|---|
| 7 | ;;
|
|---|
| 8 | ;; Portions Copyright © 2006 Clozure Associates
|
|---|
| 9 | ;; Copyright © 1996 Digitool, Inc.
|
|---|
| 10 | ;; Copyright © 1992-1995 Apple Computer, Inc.
|
|---|
| 11 | ;; All rights reserved.
|
|---|
| 12 | ;; Permission is given to use, copy, and modify this software provided
|
|---|
| 13 | ;; that Digitool is given credit in all derivative works.
|
|---|
| 14 | ;; This software is provided "as is". Digitool makes no warranty or
|
|---|
| 15 | ;; representation, either express or implied, with respect to this software,
|
|---|
| 16 | ;; its quality, accuracy, merchantability, or fitness for a particular
|
|---|
| 17 | ;; purpose.
|
|---|
| 18 | ;;
|
|---|
| 19 |
|
|---|
| 20 | ;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|---|
| 21 | ;;
|
|---|
| 22 | ;; Modification History
|
|---|
| 23 | ;;
|
|---|
| 24 | ;; 02/01/06 gz LispWorks port
|
|---|
| 25 | ;; 08/28/98 akh add dc-shared-initialize - fixes case of change class in memory, then write a slot-value to pheap
|
|---|
| 26 | ;; left us with the class updated on disk but not the instance-slots with initforms
|
|---|
| 27 | ;; ------------- 0.96
|
|---|
| 28 | ;; ------------- 0.95
|
|---|
| 29 | ;; ------------- 0.94
|
|---|
| 30 | ;; ------------- 0.93
|
|---|
| 31 | ;; ------------- 0.9
|
|---|
| 32 | ;; 11/02/94 bill (method %p-store-object (t standard-object t)) no longer
|
|---|
| 33 | ;; handles p-make-load-function-using-pheap. It has moved
|
|---|
| 34 | ;; into %p-store-internal now.
|
|---|
| 35 | ;; 10/28/94 Moon Change without-interrupts to with-databases-locked
|
|---|
| 36 | ;; 10/25/94 bill p-load-instance calls wood-disk-resident-slot-names,
|
|---|
| 37 | ;; a new GF that users can specialize.
|
|---|
| 38 | ;; define-disk-resident-slot-names macro to aid generation
|
|---|
| 39 | ;; of wood-disk-resident-slot-names methods and accessor
|
|---|
| 40 | ;; methods that will swap disk resident slots in when
|
|---|
| 41 | ;; necessary.
|
|---|
| 42 | ;; 09/21/94 bill without-interrupts as necessary for interlocking
|
|---|
| 43 | ;; -------------- 0.8
|
|---|
| 44 | ;; 10/25/93 bill initialize-persistent-instance
|
|---|
| 45 | ;; -------------- 0.6
|
|---|
| 46 | ;; 02/16/93 bill p-load-instance now calls shared-initialize to initialize
|
|---|
| 47 | ;; any new slots (slots that have been added since the instance
|
|---|
| 48 | ;; was saved to the pheap file).
|
|---|
| 49 | ;; 11/16/92 bill pheap-class-hash, p-class-instance-slot-names
|
|---|
| 50 | ;; 11/09/92 bill Make it work correctly to create two instances, p-store them,
|
|---|
| 51 | ;; redefine the class adding a slot, p-store the first instance,
|
|---|
| 52 | ;; close and reopen the pheap, then p-load the second instance.
|
|---|
| 53 | ;; chung@ils.nwu.edu found that this used to result in an instance all
|
|---|
| 54 | ;; of whose slots were unbound.
|
|---|
| 55 | ;; 08/27/92 bill in %p-store-object: call p-make-load-function
|
|---|
| 56 | ;; 08/13/92 bill (setf p-slot-value) now does the right thing if instance
|
|---|
| 57 | ;; is not a PPTR.
|
|---|
| 58 | ;; -------------- 0.5
|
|---|
| 59 | ;; 06/23/92 bill New file
|
|---|
| 60 | ;;
|
|---|
| 61 |
|
|---|
| 62 | (in-package :wood)
|
|---|
| 63 |
|
|---|
| 64 | (defun pheap-class-hash (pheap)
|
|---|
| 65 | (let ((hash (dc-class-hash (pheap-disk-cache pheap))))
|
|---|
| 66 | (when hash
|
|---|
| 67 | (pptr pheap hash))))
|
|---|
| 68 |
|
|---|
| 69 | (defun dc-class-hash (disk-cache &optional create?)
|
|---|
| 70 | (with-databases-locked
|
|---|
| 71 | (let ((res (dc-%svref disk-cache $root-vector $pheap.class-hash)))
|
|---|
| 72 | (if (eql res $pheap-nil)
|
|---|
| 73 | (if create?
|
|---|
| 74 | (setf (dc-%svref disk-cache $root-vector $pheap.class-hash)
|
|---|
| 75 | (dc-make-hash-table disk-cache)))
|
|---|
| 76 | res))))
|
|---|
| 77 |
|
|---|
| 78 | (defun p-find-class (pheap name &optional (errorp t))
|
|---|
| 79 | (multiple-value-bind (pointer imm?) (%p-store-hash-key pheap name)
|
|---|
| 80 | (when pointer
|
|---|
| 81 | (let ((res (dc-find-class (pheap-disk-cache pheap) pointer imm? errorp)))
|
|---|
| 82 | (when res (pptr pheap res))))))
|
|---|
| 83 |
|
|---|
| 84 | (defun dc-find-class (disk-cache pointer immediate? &optional (errorp t))
|
|---|
| 85 | (let ((hash (dc-class-hash disk-cache)))
|
|---|
| 86 | (or (and hash
|
|---|
| 87 | (dc-gethash disk-cache pointer immediate? hash))
|
|---|
| 88 | (when errorp
|
|---|
| 89 | (error "Class named ~s not found."
|
|---|
| 90 | (dc-pointer-load disk-cache pointer immediate?))))))
|
|---|
| 91 |
|
|---|
| 92 | ; Will overwrite an existing class
|
|---|
| 93 | (defun p-make-class (pheap name slots)
|
|---|
| 94 | (unless (and (vectorp slots) (every 'symbolp slots))
|
|---|
| 95 | (error "~s is not a vector of slot names"))
|
|---|
| 96 | (multiple-value-bind (pointer imm?) (%p-store pheap name)
|
|---|
| 97 | (pptr pheap
|
|---|
| 98 | (dc-make-class (pheap-disk-cache pheap)
|
|---|
| 99 | pointer
|
|---|
| 100 | (%p-store pheap slots)
|
|---|
| 101 | imm?
|
|---|
| 102 | slots
|
|---|
| 103 | pheap))))
|
|---|
| 104 |
|
|---|
| 105 | (defun dc-make-class (disk-cache name slots &optional name-imm? slots-object pheap)
|
|---|
| 106 | (let* ((class (dc-make-uvector disk-cache $class-size $v_class))
|
|---|
| 107 | (hash (dc-class-hash disk-cache t))
|
|---|
| 108 | (wrapper (dc-make-class-wrapper disk-cache class slots slots-object pheap)))
|
|---|
| 109 | (dc-%svfill disk-cache class
|
|---|
| 110 | ($class.name name-imm?) name
|
|---|
| 111 | $class.own-wrapper wrapper)
|
|---|
| 112 | (dc-puthash disk-cache name name-imm? hash class)))
|
|---|
| 113 |
|
|---|
| 114 | (defun dc-make-class-wrapper (disk-cache class slots &optional slots-object pheap)
|
|---|
| 115 | (let ((wrapper (dc-make-vector disk-cache $wrapper-size)))
|
|---|
| 116 | (dc-%svfill disk-cache wrapper
|
|---|
| 117 | $wrapper.class class
|
|---|
| 118 | $wrapper.slots slots)
|
|---|
| 119 | (when slots-object
|
|---|
| 120 | (setf (gethash slots-object
|
|---|
| 121 | (wrapper-hash (or pheap (disk-cache-pheap disk-cache))))
|
|---|
| 122 | wrapper))
|
|---|
| 123 | wrapper))
|
|---|
| 124 |
|
|---|
| 125 | ; Access a (disk) class'es wrapper. Update it to agree with the
|
|---|
| 126 | ; class in memory, if there is one.
|
|---|
| 127 | ; Returns 2 value:
|
|---|
| 128 | ; 1) the (possibly new) wrapper
|
|---|
| 129 | ; 2) the in-memory class, or NIL if there isn't one.
|
|---|
| 130 | ; 3) the vector of slot names for the in-memory class, or NIL
|
|---|
| 131 | ; 4) true if the class'es was obsolete.
|
|---|
| 132 | (defun dc-update-class-wrapper (disk-cache class &optional pheap memory-class dont-update)
|
|---|
| 133 | (unless pheap (setq pheap (disk-cache-pheap disk-cache)))
|
|---|
| 134 | (if (eq memory-class :none)
|
|---|
| 135 | (setq memory-class nil)
|
|---|
| 136 | (let* ((name (pointer-load pheap (dc-%svref disk-cache class $class.name) :default disk-cache)))
|
|---|
| 137 | (setq memory-class (find-class name nil))))
|
|---|
| 138 | (with-databases-locked
|
|---|
| 139 | (let ((wrapper (dc-%svref disk-cache class $class.own-wrapper))
|
|---|
| 140 | (obsolete? nil)
|
|---|
| 141 | slot-names)
|
|---|
| 142 | (when memory-class
|
|---|
| 143 | (let ((wrapper-hash (wrapper-hash pheap)))
|
|---|
| 144 | (setq slot-names (wood-slot-names-vector (class-prototype memory-class)))
|
|---|
| 145 | (unless (eql wrapper (gethash slot-names wrapper-hash))
|
|---|
| 146 | (let ((old-slot-names (pointer-load pheap (dc-%svref disk-cache wrapper $wrapper.slots)
|
|---|
| 147 | :default disk-cache)))
|
|---|
| 148 | (if (equalp old-slot-names slot-names)
|
|---|
| 149 | (setf (gethash slot-names wrapper-hash) wrapper)
|
|---|
| 150 | (progn
|
|---|
| 151 | (setq obsolete? t)
|
|---|
| 152 | (unless dont-update
|
|---|
| 153 | (setf wrapper (dc-make-class-wrapper
|
|---|
| 154 | disk-cache class
|
|---|
| 155 | (%p-store pheap slot-names) slot-names pheap)
|
|---|
| 156 | (dc-%svref disk-cache class $class.own-wrapper) wrapper))))))))
|
|---|
| 157 | (values wrapper memory-class slot-names obsolete?))))
|
|---|
| 158 |
|
|---|
| 159 |
|
|---|
| 160 | #+LispWorks
|
|---|
| 161 | (defparameter $wrapper-names-index
|
|---|
| 162 | (or (loop with wrapper = (progn
|
|---|
| 163 | (make-instance 'simple-error)
|
|---|
| 164 | (clos::class-wrapper (find-class 'simple-error)))
|
|---|
| 165 | for i in '(0 1 2 -1 -2 -3)
|
|---|
| 166 | as val = (%svref wrapper i)
|
|---|
| 167 | when (and (consp val)
|
|---|
| 168 | (consp (cdr val))
|
|---|
| 169 | (null (cddr val))
|
|---|
| 170 | (equal val '(conditions::format-string conditions::format-arguments)))
|
|---|
| 171 | return i)
|
|---|
| 172 | (error "Couldn't find wrapper names index")))
|
|---|
| 173 |
|
|---|
| 174 |
|
|---|
| 175 |
|
|---|
| 176 |
|
|---|
| 177 | ;; In lispworks, the names are in a list not a vector, but seems to work ok.
|
|---|
| 178 | (defun-inline %wrapper-instance-slots (wrapper)
|
|---|
| 179 | #+ccl (ccl::%wrapper-instance-slots wrapper)
|
|---|
| 180 | #-ccl (%svref wrapper $wrapper-names-index))
|
|---|
| 181 |
|
|---|
| 182 | #+LispWorks
|
|---|
| 183 | (defun class-own-wrapper (class)
|
|---|
| 184 | (clos::class-wrapper class))
|
|---|
| 185 |
|
|---|
| 186 | ; This knows internals of MCL's CLOS implementation
|
|---|
| 187 | (defun class-slots-vector (class)
|
|---|
| 188 | (%wrapper-instance-slots #+ccl (or (ccl::%class-own-wrapper class)
|
|---|
| 189 | (ccl::initialize-class-and-wrapper class))
|
|---|
| 190 | #+LispWorks (clos::class-wrapper class)))
|
|---|
| 191 |
|
|---|
| 192 |
|
|---|
| 193 | (defun dc-make-class-slots-vector (disk-cache class &optional
|
|---|
| 194 | (pheap (disk-cache-pheap disk-cache)))
|
|---|
| 195 | (%p-store pheap (wood-slot-names-vector (class-prototype class))))
|
|---|
| 196 |
|
|---|
| 197 | (def-predicate classp (p disk-cache pointer)
|
|---|
| 198 | (dc-vector-subtype-p disk-cache pointer $v_class))
|
|---|
| 199 |
|
|---|
| 200 | (def-accessor class-name (p) (disk-cache pointer)
|
|---|
| 201 | (require-satisfies dc-classp disk-cache pointer)
|
|---|
| 202 | (dc-%svref disk-cache pointer $class.name))
|
|---|
| 203 |
|
|---|
| 204 | (defun (setf dc-class-name) (value disk-cache class &optional value-imm?)
|
|---|
| 205 | (require-satisfies dc-classp disk-cache class)
|
|---|
| 206 | (setf (dc-%svref disk-cache class $class.name value-imm?) value)
|
|---|
| 207 | (values value value-imm?))
|
|---|
| 208 |
|
|---|
| 209 | (def-accessor class-own-wrapper (p) (disk-cache pointer)
|
|---|
| 210 | (require-satisfies dc-classp disk-cache pointer)
|
|---|
| 211 | (dc-%svref disk-cache pointer $class.own-wrapper))
|
|---|
| 212 |
|
|---|
| 213 | (defun (setf dc-class-own-wrapper) (value disk-cache class &optional value-imm?)
|
|---|
| 214 | (require-satisfies dc-classp disk-cache class)
|
|---|
| 215 | (setf (dc-%svref disk-cache class $class.own-wrapper value-imm?) value)
|
|---|
| 216 | (values value value-imm?))
|
|---|
| 217 |
|
|---|
| 218 | (defmacro dc-wrapper-class (disk-cache wrapper)
|
|---|
| 219 | `(dc-uvref ,disk-cache ,wrapper $wrapper.class))
|
|---|
| 220 |
|
|---|
| 221 | (defmacro dc-wrapper-slots (disk-cache wrapper)
|
|---|
| 222 | `(dc-uvref ,disk-cache ,wrapper $wrapper.slots))
|
|---|
| 223 |
|
|---|
| 224 | (def-accessor class-instance-slot-names (p) (disk-cache pointer)
|
|---|
| 225 | (require-satisfies dc-classp disk-cache pointer)
|
|---|
| 226 | (dc-wrapper-slots disk-cache (dc-class-own-wrapper disk-cache pointer)))
|
|---|
| 227 |
|
|---|
| 228 | (defun class-instance-slot-names (class)
|
|---|
| 229 | (let ((wrapper (class-own-wrapper class)))
|
|---|
| 230 | (unless wrapper
|
|---|
| 231 | (class-prototype class)
|
|---|
| 232 | (setq wrapper (class-own-wrapper class))
|
|---|
| 233 | (unless wrapper (error "Can't find class-own-wrapper for ~s" class)))
|
|---|
| 234 | (%wrapper-instance-slots wrapper)))
|
|---|
| 235 |
|
|---|
| 236 | (defun p-instance-class (instance)
|
|---|
| 237 | (if (pptr-p instance)
|
|---|
| 238 | (let* ((pheap (pptr-pheap instance))
|
|---|
| 239 | (disk-cache (pheap-disk-cache pheap))
|
|---|
| 240 | (pointer (pptr-pointer instance)))
|
|---|
| 241 | (pointer-load
|
|---|
| 242 | pheap
|
|---|
| 243 | (dc-wrapper-class disk-cache (dc-instance-class-wrapper disk-cache pointer))))
|
|---|
| 244 | (class-of instance)))
|
|---|
| 245 |
|
|---|
| 246 | (defmethod %p-store-object (pheap (object standard-class) descend)
|
|---|
| 247 | (let* ((disk-cache (pheap-disk-cache pheap))
|
|---|
| 248 | (descend (eq descend t))
|
|---|
| 249 | name imm?
|
|---|
| 250 | (address (maybe-cached-address pheap object
|
|---|
| 251 | (multiple-value-setq (name imm?)
|
|---|
| 252 | (%p-store pheap (class-name object)))
|
|---|
| 253 | (or (dc-find-class disk-cache name imm? nil)
|
|---|
| 254 | (progn
|
|---|
| 255 | (setq descend nil)
|
|---|
| 256 | (dc-make-class disk-cache
|
|---|
| 257 | name
|
|---|
| 258 | (dc-make-class-slots-vector
|
|---|
| 259 | disk-cache object pheap)
|
|---|
| 260 | imm?))))))
|
|---|
| 261 | (when descend
|
|---|
| 262 | (unless name
|
|---|
| 263 | (multiple-value-setq (name imm?) (%p-store pheap (class-name object))))
|
|---|
| 264 | (setf (dc-class-name disk-cache address imm?) name)
|
|---|
| 265 | (setf (dc-wrapper-slots disk-cache (dc-class-own-wrapper disk-cache address))
|
|---|
| 266 | (dc-make-class-slots-vector disk-cache object pheap)))
|
|---|
| 267 | address))
|
|---|
| 268 |
|
|---|
| 269 | (defun p-load-class (pheap disk-cache pointer depth subtype)
|
|---|
| 270 | (declare (ignore depth subtype))
|
|---|
| 271 | (maybe-cached-value pheap pointer
|
|---|
| 272 | (multiple-value-bind (name-pointer imm?) (dc-class-name disk-cache pointer)
|
|---|
| 273 | (let ((name (dc-pointer-load disk-cache name-pointer imm? pheap)))
|
|---|
| 274 | (or (find-class name nil)
|
|---|
| 275 | (let ((slots (pointer-load pheap
|
|---|
| 276 | (dc-wrapper-slots
|
|---|
| 277 | disk-cache
|
|---|
| 278 | (dc-class-own-wrapper disk-cache pointer))
|
|---|
| 279 | :default
|
|---|
| 280 | disk-cache)))
|
|---|
| 281 | ;; this is wrong - lose initargs, initforms
|
|---|
| 282 | (eval `(defclass ,name () ,(coerce slots 'list)))))))))
|
|---|
| 283 |
|
|---|
| 284 | (defmethod p-allocate-instance (pheap (class symbol))
|
|---|
| 285 | (p-allocate-instance pheap (or (p-find-class pheap class nil)
|
|---|
| 286 | (p-store pheap (find-class class)))))
|
|---|
| 287 |
|
|---|
| 288 | (defmethod p-allocate-instance (pheap (class standard-class))
|
|---|
| 289 | (p-%allocate-instance pheap (p-store pheap class) class))
|
|---|
| 290 |
|
|---|
| 291 | (defmethod p-allocate-instance (pheap (class pptr))
|
|---|
| 292 | (require-satisfies p-classp class)
|
|---|
| 293 | (p-%allocate-instance pheap class nil))
|
|---|
| 294 |
|
|---|
| 295 | (defun p-%allocate-instance (pheap class memory-class)
|
|---|
| 296 | (pptr pheap (dc-%allocate-instance (pheap-disk-cache pheap) (pptr-pointer class) memory-class)))
|
|---|
| 297 |
|
|---|
| 298 | (defun dc-%allocate-instance (disk-cache class &optional memory-class)
|
|---|
| 299 | (let* ((wrapper (dc-update-class-wrapper disk-cache class nil memory-class))
|
|---|
| 300 | (slots (dc-make-vector
|
|---|
| 301 | disk-cache
|
|---|
| 302 | (dc-length disk-cache (dc-wrapper-slots disk-cache wrapper))
|
|---|
| 303 | nil (%unbound-marker) t))
|
|---|
| 304 | (res (dc-make-uvector disk-cache $instance-size $v_instance)))
|
|---|
| 305 | (dc-%svfill disk-cache res
|
|---|
| 306 | $instance.wrapper wrapper
|
|---|
| 307 | $instance.slots slots)
|
|---|
| 308 | res))
|
|---|
| 309 |
|
|---|
| 310 | (def-accessor instance-class-wrapper (p) (disk-cache pointer)
|
|---|
| 311 | (require-satisfies dc-standard-instance-p disk-cache pointer)
|
|---|
| 312 | (dc-%svref disk-cache pointer $instance.wrapper))
|
|---|
| 313 |
|
|---|
| 314 | ; This is the wrong name. Check the MOP
|
|---|
| 315 | (def-accessor instance-access (p index) (disk-cache pointer)
|
|---|
| 316 | (require-satisfies dc-standard-instance-p disk-cache pointer)
|
|---|
| 317 | (dc-uvref disk-cache (dc-%svref disk-cache pointer $instance.slots) index))
|
|---|
| 318 |
|
|---|
| 319 | (defun (setf p-instance-access) (value p index)
|
|---|
| 320 | (setq index (require-type index 'fixnum))
|
|---|
| 321 | (if (pptr-p p)
|
|---|
| 322 | (let ((pheap (pptr-pheap p)))
|
|---|
| 323 | (multiple-value-bind (v imm?) (%p-store pheap value)
|
|---|
| 324 | (setf (dc-instance-access
|
|---|
| 325 | (pheap-disk-cache pheap) (pptr-pointer p) index imm?)
|
|---|
| 326 | v)
|
|---|
| 327 | (if imm? v (pptr pheap v))))
|
|---|
| 328 | (error "~s is defined only for Wood instances" '(setf p-instance-access))))
|
|---|
| 329 |
|
|---|
| 330 | (defun (setf dc-instance-access) (value disk-cache pointer index value-imm?)
|
|---|
| 331 | (require-satisfies dc-standard-instance-p disk-cache pointer)
|
|---|
| 332 | (setf (dc-uvref disk-cache (dc-%svref disk-cache pointer $instance.slots)
|
|---|
| 333 | index value-imm?)
|
|---|
| 334 | value))
|
|---|
| 335 |
|
|---|
| 336 | (defun instance-access (thing index)
|
|---|
| 337 | (declare (ignore thing index))
|
|---|
| 338 | (error "~s is defined only for Wood instances" 'instance-access))
|
|---|
| 339 |
|
|---|
| 340 | ; Instance is an on-disk address.
|
|---|
| 341 | ; class is an in-memory class or NIL.
|
|---|
| 342 | ; Returns three values:
|
|---|
| 343 | ; 1) The slots vector on disk
|
|---|
| 344 | ; 2) The slot names vector in memory.
|
|---|
| 345 | ; 3) slot-names vector if the instance was obsolete.
|
|---|
| 346 | ; This will be different from the second value if the
|
|---|
| 347 | ; dont-update arg is true.
|
|---|
| 348 | ;
|
|---|
| 349 | ; This is hairy because it has to deal with a lot of possibilities:
|
|---|
| 350 | ;
|
|---|
| 351 | ; 1) Class exists in memory, but hasn't been associated with PHEAP yet.
|
|---|
| 352 | ; 2) Class exists in memeory and has been associated with PHEAP.
|
|---|
| 353 | ; 3) Class does not exist in memory.
|
|---|
| 354 | ; 4) 1 or 2 and the class has been redefined since the instance was stored in the PHEAP.
|
|---|
| 355 | (defun dc-updated-instance-slots (disk-cache instance memory-class pheap &optional
|
|---|
| 356 | dont-update)
|
|---|
| 357 | ;(assert (dc-vector-subtype-p disk-cache instance $v_instance))
|
|---|
| 358 | (with-databases-locked
|
|---|
| 359 | (let ((old-wrapper (dc-%svref disk-cache instance $instance.wrapper))
|
|---|
| 360 | (instance-slots (dc-%svref disk-cache instance $instance.slots))
|
|---|
| 361 | class wrapper slot-names old-slot-names obsolete?)
|
|---|
| 362 | (if memory-class
|
|---|
| 363 | (progn
|
|---|
| 364 | (setq slot-names (wood-slot-names-vector (class-prototype memory-class)))
|
|---|
| 365 | (setq wrapper (gethash slot-names (wrapper-hash pheap))))
|
|---|
| 366 | (progn
|
|---|
| 367 | (setq class (dc-%svref disk-cache old-wrapper $wrapper.class))
|
|---|
| 368 | (multiple-value-setq (wrapper memory-class slot-names obsolete?)
|
|---|
| 369 | (dc-update-class-wrapper disk-cache class pheap nil dont-update))
|
|---|
| 370 | (unless slot-names
|
|---|
| 371 | (setq slot-names (pointer-load pheap (dc-%svref disk-cache old-wrapper $wrapper.slots)
|
|---|
| 372 | :default disk-cache)
|
|---|
| 373 | wrapper old-wrapper))))
|
|---|
| 374 | (if (if (and wrapper (not obsolete?))
|
|---|
| 375 | (eql wrapper old-wrapper)
|
|---|
| 376 | (when (equalp slot-names
|
|---|
| 377 | (setq old-slot-names
|
|---|
| 378 | (pointer-load pheap (dc-%svref disk-cache old-wrapper $wrapper.slots)
|
|---|
| 379 | :default disk-cache)))
|
|---|
| 380 | (setq wrapper (setf (gethash slot-names (wrapper-hash pheap)) old-wrapper))))
|
|---|
| 381 | ; Wrapper is current
|
|---|
| 382 | (values instance-slots slot-names)
|
|---|
| 383 | ; Wrapper needs updating.
|
|---|
| 384 | (progn
|
|---|
| 385 | (unless old-slot-names
|
|---|
| 386 | (setq old-slot-names (pointer-load
|
|---|
| 387 | pheap
|
|---|
| 388 | (dc-%svref disk-cache old-wrapper $wrapper.slots)
|
|---|
| 389 | :default disk-cache)))
|
|---|
| 390 | (if dont-update
|
|---|
| 391 | (values instance-slots old-slot-names slot-names)
|
|---|
| 392 | (let* ((slot-count (length slot-names))
|
|---|
| 393 | (slot-values (make-array slot-count))
|
|---|
| 394 | (slot-imms (make-array slot-count)))
|
|---|
| 395 | (declare (fixnum slot-count))
|
|---|
| 396 | ;(dynamic-extent slot-values slot-imms))
|
|---|
| 397 | (unless wrapper
|
|---|
| 398 | (let ((class (dc-%svref disk-cache old-wrapper $wrapper.class)))
|
|---|
| 399 | (setq wrapper (dc-update-class-wrapper disk-cache class pheap memory-class dont-update))))
|
|---|
| 400 | (dotimes (i slot-count)
|
|---|
| 401 | (let ((index (position (svref slot-names i) old-slot-names :test 'eq)))
|
|---|
| 402 | (if index
|
|---|
| 403 | (multiple-value-bind (value imm?) (dc-uvref disk-cache instance-slots index)
|
|---|
| 404 | (setf (svref slot-values i) value
|
|---|
| 405 | (svref slot-imms i) imm?))
|
|---|
| 406 | (setf (svref slot-values i) (%unbound-marker)
|
|---|
| 407 | (svref slot-imms i) t))))
|
|---|
| 408 | (let* ((old-instance-length (dc-length disk-cache instance-slots))
|
|---|
| 409 | (new-instance-slots (if (>= old-instance-length slot-count)
|
|---|
| 410 | (let ((index slot-count))
|
|---|
| 411 | (dotimes (i (- old-instance-length slot-count))
|
|---|
| 412 | (setf (dc-uvref disk-cache instance-slots index t)
|
|---|
| 413 | (%unbound-marker)))
|
|---|
| 414 | instance-slots)
|
|---|
| 415 | (dc-make-vector
|
|---|
| 416 | disk-cache slot-count
|
|---|
| 417 | (dc-area disk-cache instance-slots)
|
|---|
| 418 | (%unbound-marker) t))))
|
|---|
| 419 | (dotimes (i slot-count)
|
|---|
| 420 | (let ((value (svref slot-values i))
|
|---|
| 421 | (imm? (svref slot-imms i)))
|
|---|
| 422 | (unless (and imm? (eq value (%unbound-marker)))
|
|---|
| 423 | (setf (dc-%svref disk-cache new-instance-slots i imm?) value))))
|
|---|
| 424 | (dc-shared-initialize disk-cache pheap slot-values new-instance-slots memory-class)
|
|---|
| 425 | (setf (dc-%svref disk-cache instance $instance.wrapper) wrapper
|
|---|
| 426 | (dc-%svref disk-cache instance $instance.slots) new-instance-slots)
|
|---|
| 427 | (values new-instance-slots slot-names)))))))))
|
|---|
| 428 |
|
|---|
| 429 |
|
|---|
| 430 | ;;; *** TODO: Need Lispworks version.
|
|---|
| 431 | #+CCL
|
|---|
| 432 | (defun dc-shared-initialize (disk-cache pheap slot-values new-instance-slots class &optional (slot-names t))
|
|---|
| 433 | ;; I don't know how to find all this stuff in the disk version - I don't think it's there.
|
|---|
| 434 | ;; copied from %shared-initialize
|
|---|
| 435 | (when class
|
|---|
| 436 | (dotimes (i (uvsize (ccl::%class-instance-slotds class)))
|
|---|
| 437 | (declare (fixnum i))
|
|---|
| 438 | (let* ((slotd (svref (ccl::%class-instance-slotds class) i))
|
|---|
| 439 | (index i)
|
|---|
| 440 | (initform (ccl::%slotd-initform slotd)))
|
|---|
| 441 | (when (and initform
|
|---|
| 442 | (eq (svref slot-values index) (%unbound-marker))
|
|---|
| 443 | (or (eq slot-names t) (memq (ccl::%slotd-name slotd) slot-names)))
|
|---|
| 444 | (let ((value
|
|---|
| 445 | (if (listp initform) ;(value)
|
|---|
| 446 | (car initform)
|
|---|
| 447 | (funcall initform))))
|
|---|
| 448 | (multiple-value-bind (v imm?) (%p-store pheap value)
|
|---|
| 449 | (setf (dc-%svref disk-cache new-instance-slots index imm?) v))))))))
|
|---|
| 450 |
|
|---|
| 451 |
|
|---|
| 452 |
|
|---|
| 453 | (def-predicate standard-instance-p (p disk-cache pointer)
|
|---|
| 454 | (and (dc-uvectorp disk-cache pointer)
|
|---|
| 455 | (dc-vector-subtype-p disk-cache pointer $v_instance)))
|
|---|
| 456 |
|
|---|
| 457 | (def-accessor slot-value (p slot-name) (disk-cache pointer)
|
|---|
| 458 | (require-satisfies dc-standard-instance-p disk-cache pointer)
|
|---|
| 459 | (multiple-value-bind (value imm?)
|
|---|
| 460 | (dc-%slot-value disk-cache pointer slot-name)
|
|---|
| 461 | (if (and imm? (eq value (%unbound-marker)))
|
|---|
| 462 | (dc-slot-unbound disk-cache pointer slot-name)
|
|---|
| 463 | (values value imm?))))
|
|---|
| 464 |
|
|---|
| 465 | (defun dc-%slot-value (disk-cache pointer slot-name)
|
|---|
| 466 | (multiple-value-bind (slots index)
|
|---|
| 467 | (dc-%slot-vector-and-index disk-cache pointer slot-name t)
|
|---|
| 468 | (if slots
|
|---|
| 469 | (if (eq slots (%unbound-marker))
|
|---|
| 470 | (values slots t)
|
|---|
| 471 | (dc-%svref disk-cache slots index))
|
|---|
| 472 | (dc-slot-missing disk-cache pointer slot-name 'slot-value))))
|
|---|
| 473 |
|
|---|
| 474 | (defun dc-slot-missing (disk-cache pointer slot-name operation &optional new-value)
|
|---|
| 475 | (declare (ignore operation new-value))
|
|---|
| 476 | (error "~s has no slot named ~s"
|
|---|
| 477 | (pptr (disk-cache-pheap disk-cache) pointer) slot-name))
|
|---|
| 478 |
|
|---|
| 479 | (defun dc-slot-unbound (disk-cache pointer slot-name)
|
|---|
| 480 | (error "Slot ~s is unbound in ~s"
|
|---|
| 481 | slot-name (pptr (disk-cache-pheap disk-cache) pointer)))
|
|---|
| 482 |
|
|---|
| 483 | ; Returns two values:
|
|---|
| 484 | ; 1) disk-cache vector of slots
|
|---|
| 485 | ; 2) index in the vector
|
|---|
| 486 | ;
|
|---|
| 487 | ; If the slot doesn't exist, returns NIL.
|
|---|
| 488 | ; If the slot exists, but only after the instance is updated and dont-update
|
|---|
| 489 | ; is true, returns (%unbound-marker).
|
|---|
| 490 | (defun dc-%slot-vector-and-index (disk-cache pointer slot-name &optional dont-update)
|
|---|
| 491 | (let* ((pheap (disk-cache-pheap disk-cache))
|
|---|
| 492 | (wrapper (dc-%svref disk-cache pointer $instance.wrapper))
|
|---|
| 493 | (memory-class (pointer-load
|
|---|
| 494 | pheap
|
|---|
| 495 | (dc-%svref disk-cache
|
|---|
| 496 | (dc-%svref disk-cache wrapper $wrapper.class)
|
|---|
| 497 | $class.name)
|
|---|
| 498 | :default disk-cache)))
|
|---|
| 499 | (multiple-value-bind (slots slot-names real-slot-names)
|
|---|
| 500 | (dc-updated-instance-slots
|
|---|
| 501 | disk-cache pointer
|
|---|
| 502 | (find-class
|
|---|
| 503 | memory-class
|
|---|
| 504 | nil)
|
|---|
| 505 | pheap
|
|---|
| 506 | dont-update)
|
|---|
| 507 | (let ((index (position slot-name slot-names :test 'eq))
|
|---|
| 508 | (real-index (and dont-update
|
|---|
| 509 | real-slot-names
|
|---|
| 510 | (position slot-name real-slot-names))))
|
|---|
| 511 | (if (and index (or (not dont-update) (not real-slot-names) real-index))
|
|---|
| 512 | (values slots index)
|
|---|
| 513 | (if real-index
|
|---|
| 514 | (%unbound-marker)
|
|---|
| 515 | nil))))))
|
|---|
| 516 |
|
|---|
| 517 | (defun (setf p-slot-value) (value p slot-name)
|
|---|
| 518 | (if (pptr-p p)
|
|---|
| 519 | (let* ((pheap (pptr-pheap p))
|
|---|
| 520 | (disk-cache (pheap-disk-cache pheap))
|
|---|
| 521 | (pointer (pptr-pointer p)))
|
|---|
| 522 | (multiple-value-bind (slots index)
|
|---|
| 523 | (dc-%slot-vector-and-index disk-cache pointer slot-name)
|
|---|
| 524 | (unless slots
|
|---|
| 525 | (dc-slot-missing disk-cache pointer slot-name '(setf p-slot-value)))
|
|---|
| 526 | (multiple-value-bind (v imm?) (%p-store pheap value)
|
|---|
| 527 | (setf (dc-%svref disk-cache slots index imm?) v)
|
|---|
| 528 | (if imm?
|
|---|
| 529 | v
|
|---|
| 530 | (pptr pheap v)))))
|
|---|
| 531 | (setf (slot-value p slot-name) value)))
|
|---|
| 532 |
|
|---|
| 533 | (def-accessor slot-boundp (p slot-name) (disk-cache pointer)
|
|---|
| 534 | (values (not (eq (dc-%slot-value disk-cache pointer slot-name)
|
|---|
| 535 | (%unbound-marker)))
|
|---|
| 536 | t))
|
|---|
| 537 |
|
|---|
| 538 | (def-accessor slot-makunbound (p slot-name) (disk-cache pointer)
|
|---|
| 539 | (multiple-value-bind (slots index)
|
|---|
| 540 | (dc-%slot-vector-and-index disk-cache pointer slot-name t)
|
|---|
| 541 | (unless slots
|
|---|
| 542 | (dc-slot-missing disk-cache pointer slot-name 'p-slot-makunbound))
|
|---|
| 543 | (unless (eq slots (%unbound-marker))
|
|---|
| 544 | (setf (dc-%svref disk-cache slots index t) (%unbound-marker)))
|
|---|
| 545 | pointer))
|
|---|
| 546 |
|
|---|
| 547 | #+CCL
|
|---|
| 548 | (defmethod %p-store-object (pheap (object ccl::funcallable-standard-object) descend)
|
|---|
| 549 | (declare (ignore pheap descend))
|
|---|
| 550 | (error "Can't save generic functions yet. Maybe never."))
|
|---|
| 551 |
|
|---|
| 552 | ; this will do the wrong thing if anyone redefines the class
|
|---|
| 553 | ; of the object while it is running.
|
|---|
| 554 | (defmethod %p-store-object (pheap (object standard-object) descend)
|
|---|
| 555 | (let* ((class (class-of object))
|
|---|
| 556 | (consed? nil))
|
|---|
| 557 | (%p-store-object-body (pheap object descend disk-cache address)
|
|---|
| 558 | (progn
|
|---|
| 559 | (setq consed? t)
|
|---|
| 560 | (dc-%allocate-instance disk-cache (%p-store pheap class)))
|
|---|
| 561 | (progn
|
|---|
| 562 | (unless consed?
|
|---|
| 563 | ; Ensure that p-make-load-function-using-pheap method didn't change too much to handle
|
|---|
| 564 | (require-satisfies dc-vector-subtype-p disk-cache address $v_instance))
|
|---|
| 565 | (multiple-value-bind (slots slot-names)
|
|---|
| 566 | (dc-updated-instance-slots disk-cache address class pheap)
|
|---|
| 567 | (dotimes (i (length slot-names))
|
|---|
| 568 | (let ((slot-name (elt slot-names i)))
|
|---|
| 569 | (multiple-value-bind (value imm?)
|
|---|
| 570 | (if (slot-boundp object slot-name)
|
|---|
| 571 | (%p-store pheap (wood-slot-value object slot-name) descend)
|
|---|
| 572 | (values (%unbound-marker) t))
|
|---|
| 573 | (setf (dc-uvref disk-cache slots i imm?) value)))))))))
|
|---|
| 574 |
|
|---|
| 575 | ; New functions
|
|---|
| 576 | ; Allows a p-make-load-function-using-pheap method to save slots for an object
|
|---|
| 577 | ; and do something else as well.
|
|---|
| 578 |
|
|---|
| 579 | (defmethod instance-slot-names ((instance structure-object))
|
|---|
| 580 | #+ccl
|
|---|
| 581 | (let ((sd (gethash (car (%svref instance 0)) ccl::%defstructs%))
|
|---|
| 582 | (res nil))
|
|---|
| 583 | (dolist (slot (%svref sd 1)) ;; sd-slots
|
|---|
| 584 | (let ((name (car slot)))
|
|---|
| 585 | (when (symbolp name)
|
|---|
| 586 | (push name res))))
|
|---|
| 587 | (nreverse res))
|
|---|
| 588 | #+LispWorks
|
|---|
| 589 | (structure:structure-class-slot-names (class-of instance)))
|
|---|
| 590 |
|
|---|
| 591 | (defmethod instance-slot-names ((instance standard-object))
|
|---|
| 592 | (mapcar 'slot-definition-name (class-instance-slots (class-of instance))))
|
|---|
| 593 |
|
|---|
| 594 | (defmethod p-make-load-function-saving-slots ((object standard-object) &optional (slots nil slots-p))
|
|---|
| 595 | (%p-make-load-function-saving-slots object slots slots-p))
|
|---|
| 596 |
|
|---|
| 597 | (defmethod p-make-load-function-saving-slots ((object structure-object) &optional (slots nil slots-p))
|
|---|
| 598 | (%p-make-load-function-saving-slots object slots slots-p))
|
|---|
| 599 |
|
|---|
| 600 | (defun %p-make-load-function-saving-slots (object slots slots-p)
|
|---|
| 601 | (let* ((slot-names (if slots-p slots (instance-slot-names object)))
|
|---|
| 602 | (mapper #'(lambda (slot)
|
|---|
| 603 | (if (slot-boundp object slot)
|
|---|
| 604 | (slot-value object slot)
|
|---|
| 605 | (%unbound-marker))))
|
|---|
| 606 | (slot-values (mapcar mapper slot-names)))
|
|---|
| 607 | (declare (dynamic-extent mapper))
|
|---|
| 608 | (values `(allocate-instance-of-class ,(class-name (class-of object)))
|
|---|
| 609 | (when slot-names
|
|---|
| 610 | `(%set-slot-values ,object ,slot-names ,slot-values)))))
|
|---|
| 611 |
|
|---|
| 612 | (defun allocate-instance-of-class (class-name)
|
|---|
| 613 | (allocate-instance (find-class class-name)))
|
|---|
| 614 |
|
|---|
| 615 | (defun progn-load-functions (&rest load-functions)
|
|---|
| 616 | (declare (dynamic-extent load-functions))
|
|---|
| 617 | (when load-functions
|
|---|
| 618 | (do* ((this load-functions next)
|
|---|
| 619 | (next (cdr this) (cdr this)))
|
|---|
| 620 | ((null next) (apply 'funcall (car this)))
|
|---|
| 621 | (apply 'funcall (car this)))))
|
|---|
| 622 |
|
|---|
| 623 | (defun progn-init-functions (object &rest init-functions)
|
|---|
| 624 | (declare (dynamic-extent init-functions))
|
|---|
| 625 | (dolist (f.args init-functions)
|
|---|
| 626 | (apply (car f.args) object (cdr f.args))))
|
|---|
| 627 |
|
|---|
| 628 | (defun p-load-instance (pheap disk-cache pointer depth subtype)
|
|---|
| 629 | (declare (ignore subtype))
|
|---|
| 630 | (let* ((cached? t)
|
|---|
| 631 | class
|
|---|
| 632 | (instance (maybe-cached-value pheap pointer
|
|---|
| 633 | (setq cached? nil)
|
|---|
| 634 | (if (null depth)
|
|---|
| 635 | (return-from p-load-instance (pptr pheap pointer)))
|
|---|
| 636 | (setq class (pointer-load pheap
|
|---|
| 637 | (dc-%svref disk-cache
|
|---|
| 638 | (dc-instance-class-wrapper
|
|---|
| 639 | disk-cache pointer)
|
|---|
| 640 | $wrapper.class)
|
|---|
| 641 | :default
|
|---|
| 642 | disk-cache))
|
|---|
| 643 | (allocate-instance class))))
|
|---|
| 644 | (when (or (not cached?)
|
|---|
| 645 | (and (eq depth t)
|
|---|
| 646 | (let ((p-load-hash (p-load-hash pheap)))
|
|---|
| 647 | (unless (gethash instance p-load-hash)
|
|---|
| 648 | (setf (gethash instance p-load-hash) instance)))))
|
|---|
| 649 | (let ((next-level-depth (cond ((or (eq depth :single) (fixnump depth)) nil)
|
|---|
| 650 | (t depth)))
|
|---|
| 651 | (disk-resident-slots (wood-disk-resident-slot-names instance)))
|
|---|
| 652 | (multiple-value-bind (slot-vector slot-names real-slot-names)
|
|---|
| 653 | (dc-updated-instance-slots
|
|---|
| 654 | disk-cache pointer class pheap t)
|
|---|
| 655 | (dotimes (i (length slot-names))
|
|---|
| 656 | (let ((slot-name (elt slot-names i)))
|
|---|
| 657 | (when (or (null real-slot-names) (position slot-name real-slot-names))
|
|---|
| 658 | (multiple-value-bind (pointer immediate?)
|
|---|
| 659 | (dc-%svref disk-cache slot-vector i)
|
|---|
| 660 | (if immediate?
|
|---|
| 661 | (if (eq pointer (%unbound-marker))
|
|---|
| 662 | (slot-makunbound instance slot-name)
|
|---|
| 663 | (setf (wood-slot-value instance slot-name) pointer))
|
|---|
| 664 | (setf (wood-slot-value instance slot-name)
|
|---|
| 665 | (if (member slot-name disk-resident-slots :test #'eq)
|
|---|
| 666 | (pptr pheap pointer)
|
|---|
| 667 | (pointer-load pheap pointer next-level-depth disk-cache))))))))
|
|---|
| 668 | (when real-slot-names
|
|---|
| 669 | (let (new-slot-names)
|
|---|
| 670 | (dotimes (i (length real-slot-names))
|
|---|
| 671 | (let ((slot-name (svref real-slot-names i)))
|
|---|
| 672 | (unless (position slot-name slot-names)
|
|---|
| 673 | (push slot-name new-slot-names))))
|
|---|
| 674 | (when new-slot-names
|
|---|
| 675 | (shared-initialize instance new-slot-names))))))
|
|---|
| 676 | (unless cached?
|
|---|
| 677 | (initialize-persistent-instance instance)))
|
|---|
| 678 | instance))
|
|---|
| 679 |
|
|---|
| 680 |
|
|---|
| 681 | ; These methods allow users to specialize the way that CLOS instances are saved.
|
|---|
| 682 |
|
|---|
| 683 | ; Return a vector of the names of the slots to be saved for an instance.
|
|---|
| 684 | ; The instance saving code assumes that multiple calls to this
|
|---|
| 685 | ; method will return the same (EQ) vector unless the class has been redefined.
|
|---|
| 686 | ; May be called with a CLASS-PROTOTYPE, so don't expect any of the slots
|
|---|
| 687 | ; to contain useful information.
|
|---|
| 688 | (defmethod wood-slot-names-vector ((object standard-object))
|
|---|
| 689 | (class-slots-vector (class-of object)))
|
|---|
| 690 |
|
|---|
| 691 | ; These allow specialization of slot-value.
|
|---|
| 692 | ; Some slots may want to be saved in a different format,
|
|---|
| 693 | ; or interned on the way back in.
|
|---|
| 694 | (defmethod wood-slot-value ((object standard-object) slot-name)
|
|---|
| 695 | (slot-value object slot-name))
|
|---|
| 696 |
|
|---|
| 697 | (defmethod (setf wood-slot-value) (value (object standard-object) slot-name)
|
|---|
| 698 | (setf (slot-value object slot-name) value))
|
|---|
| 699 |
|
|---|
| 700 |
|
|---|
| 701 | ; This generic function is called on a newly loaded CLOS instance
|
|---|
| 702 | (defmethod initialize-persistent-instance (instance)
|
|---|
| 703 | (declare (ignore instance))
|
|---|
| 704 | nil)
|
|---|
| 705 |
|
|---|
| 706 |
|
|---|
| 707 | ; This generic function is called when an instance is p-load'ed to
|
|---|
| 708 | ; determine which slots should remain disk resident and have pptr's
|
|---|
| 709 | ; put in the instance.
|
|---|
| 710 | (defgeneric wood-disk-resident-slot-names (instance)
|
|---|
| 711 | (:method ((instance t))
|
|---|
| 712 | nil))
|
|---|
| 713 |
|
|---|
| 714 | (declaim (inline default-slot-value-processor))
|
|---|
| 715 |
|
|---|
| 716 | (defun default-slot-value-processor (instance slot-name value sticky p-loader pass-instance-to-p-loader)
|
|---|
| 717 | (if (pptr-p value)
|
|---|
| 718 | (let ((loaded-value
|
|---|
| 719 | (if pass-instance-to-p-loader
|
|---|
| 720 | (funcall p-loader instance value)
|
|---|
| 721 | (funcall p-loader value))))
|
|---|
| 722 | (when sticky
|
|---|
| 723 | (setf (slot-value instance slot-name) loaded-value))
|
|---|
| 724 | loaded-value)
|
|---|
| 725 | value))
|
|---|
| 726 |
|
|---|
| 727 | ; An easy way to define a wood-disk-resident-slot-names method
|
|---|
| 728 | ; and some :around methods on slot accessors to swap the slots
|
|---|
| 729 | ; in on demand.
|
|---|
| 730 | (defmacro define-disk-resident-slots ((class-name &key
|
|---|
| 731 | sticky
|
|---|
| 732 | (p-loader ''p-load)
|
|---|
| 733 | pass-instance-to-p-loader
|
|---|
| 734 | (slot-value-processor '#'default-slot-value-processor))
|
|---|
| 735 | &body slots-and-accessors)
|
|---|
| 736 | (let* ((sticky-p #'(lambda (slot-and-accessor)
|
|---|
| 737 | (let ((cell (and (listp slot-and-accessor) (cddr slot-and-accessor))))
|
|---|
| 738 | (if cell (car cell) sticky))))
|
|---|
| 739 | (slots (mapcar #'(lambda (x) (if (listp x) (first x) x)) slots-and-accessors))
|
|---|
| 740 | (accessors (mapcar #'(lambda (x) (if (listp x) (second x) x)) slots-and-accessors))
|
|---|
| 741 | (stickies (mapcar sticky-p slots-and-accessors))
|
|---|
| 742 | (class (find-class class-name nil))
|
|---|
| 743 | (instance (make-symbol (symbol-name class-name))))
|
|---|
| 744 | (declare (dynamic-extent sticky-p))
|
|---|
| 745 | (flet ((require-symbol (x) (require-type x 'symbol)))
|
|---|
| 746 | (mapc #'require-symbol slots)
|
|---|
| 747 | (mapc #'require-symbol accessors))
|
|---|
| 748 | (when class
|
|---|
| 749 | (let* ((class-slots (mapcar 'slot-definition-name (class-instance-slots class))))
|
|---|
| 750 | (flet ((require-slot (slot)
|
|---|
| 751 | (unless (member slot class-slots :test 'eq)
|
|---|
| 752 | (warn "~s is not an instance slot of ~s" slot class))))
|
|---|
| 753 | (declare (dynamic-extent #'require-slot))
|
|---|
| 754 | (mapc #'require-slot slots))))
|
|---|
| 755 | `(progn
|
|---|
| 756 | ,@(loop for slot in slots
|
|---|
| 757 | for accessor in accessors
|
|---|
| 758 | for sticky in stickies
|
|---|
| 759 | collect
|
|---|
| 760 | `(defmethod ,accessor :around ((,instance ,class-name))
|
|---|
| 761 | (funcall ,slot-value-processor
|
|---|
| 762 | ,instance
|
|---|
| 763 | ',slot
|
|---|
| 764 | (call-next-method)
|
|---|
| 765 | ,(not (null sticky))
|
|---|
| 766 | ,p-loader
|
|---|
| 767 | ,(not (null pass-instance-to-p-loader)))))
|
|---|
| 768 | (defmethod wood-disk-resident-slot-names ((,class-name ,class-name))
|
|---|
| 769 | ',slots)
|
|---|
| 770 | (record-source-file ',class-name :disk-resident-slots)
|
|---|
| 771 | ',class-name)))
|
|---|
| 772 |
|
|---|
| 773 |
|
|---|
| 774 |
|
|---|
| 775 | ;;; 1 3/10/94 bill 1.8d247
|
|---|
| 776 | ;;; 2 7/26/94 Derek 1.9d027
|
|---|
| 777 | ;;; 3 10/04/94 bill 1.9d071
|
|---|
| 778 | ;;; 4 11/01/94 Derek 1.9d085 Bill's Saving Library Task
|
|---|
| 779 | ;;; 5 11/03/94 Moon 1.9d086
|
|---|
| 780 | ;;; 6 11/05/94 kab 1.9d087
|
|---|
| 781 | ;;; 2 3/23/95 bill 1.11d010
|
|---|