[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Dumping data structures with circular references.

  From: "RDP%ALAN.LAAC-AI.Dialnet.Symbolics.COM %ALAN.kahuna.DECNET.LOCKHEED.COM"@warbucks.ai.sri.com
  Date: Fri, 3 Nov 89 11:22:17 CST
  To: slug@warbucks.ai.sri.com
  Subject: Dumping data structures with circular references.
  Many thanks for the replies so far (keep those cards and letters
  coming!).  I'm pursuing one additional item on this topic and it
  involves dumping the data in two passes.  The problem is that
  SYS:DUMP-FORMS-TO-FILE takes a filename rather than a stream and it
  doesn't allow me to say "append".  
  Anyone have an idea how best to solve this?  Maybe write two separate
  files with SYS:DUMP-FORMS-TO-FILE and then append them after the fact?
  Is it easy to append two binary files (or are there subtleties of the
  file format that will screw me)?  Or if I had the equivalent of
  SYS:DUMP-FORMS-TO-STREAM I guess I would be home free.  Then, I could
  simply do my own WITH-OPEN-FILE once and call SYS:DUMP-FORMS-TO-STREAM
  twice on it.
  Thanks again for any insight on this topic.
This is part of dumping code we use for PCL objects, which are flavor
instances.  It can be easily modified to work with normal flavors.
The :FASD-FORM simply returns a form that makes an instance, and
appends additional dump instructions onto *after-fasd-forms*.  Since
the instances exist when the *after-fasd-forms* are dumped, there is
no cicrularity problem.

It would be better if rather than a full make-instance (making and
object and initializing it), one just allocated space it.

(defvar *after-fasd-forms* nil
  "Forms to dump after instances are made.")

;;; This is a version of SI:DUMP-FORMS-TO-FILE that lets you send messages to
;;; instance after you create them, so you can avoid circular references.
(defun DUMP-FORMS-TO-FILE (filename forms &optional file-attribute-list)
  ;; If no package is specified for the file, use the USER package.
  (let ((*after-fasd-forms* nil))
    (unless (zl:get (scl:locf file-attribute-list) ':package)
      (zl:putprop (scl:locf file-attribute-list) ':user ':package))
    (si:writing-bin-file (stream filename)
      (si:dump-attribute-list file-attribute-list stream)
      (dolist (form forms)
	(si:dump-form-to-eval form stream)
	  (if *after-fasd-forms*
	      (si:dump-form-to-eval (pop *after-fasd-forms*) stream)
	      (return nil)))))))

(flavor:defmethod (:FASD-FORM PCL:IWMC-CLASS) ()
  ;; We use the fact that instance with metaclass class are considered flavors by LISPM
  ;; So we just provide a :fasd-form that works with DUMP-FORMS-TO-FILE
  (setq *after-fasd-forms*
	(nconc `((load-slots ',scl:self ,@(dump-items scl:self))
		 ,@(after-dump-forms scl:self)
		 (after-load ',scl:self))))
  `(pcl:make-instance ',(class-name (class-of scl:self))))

(defgeneric DUMP-ITEMS (object)
  (:method-combination append)
  (:documentation "Returns a list of slot-name slot-value pairs.
these are used to restore a new instance of the object.  Slot values may
refer to the object."))