Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
245 lines (200 sloc) 8.74 KB
;; -*- mode: Lisp; Syntax: Common-Lisp; Package: cells; -*-
Cells -- Automatic Dataflow Managememnt
Copyright (C) 1995, 2006 by Kenneth Tilton
This library is free software; you can redistribute it and/or
modify it under the terms of the Lisp Lesser GNU Public License
(, known as the LLGPL.
This library is distributed WITHOUT ANY WARRANTY; without even
See the Lisp Lesser GNU Public License for more details.
(in-package :cells)
(defun md-awake (self) (eql :awake (md-state self)))
(defun fm-grandparent (md)
(fm-parent (fm-parent md)))
(defmethod md-release (other)
(declare (ignorable other)))
(export! mdead)
;___________________ birth / death__________________________________
(defgeneric mdead (self)
(:method ((self model-object))
(unless *not-to-be* ;; weird
(eq :eternal-rest (md-state self))))
(:method (self)
(declare (ignore self))
(defgeneric not-to-be (self)
(:method (other)
(declare (ignore other)))
(:method ((self cons))
(not-to-be (car self))
(not-to-be (cdr self)))
(:method ((self array))
(loop for s across self
do (not-to-be s)))
(:method ((self hash-table))
(maphash (lambda (k v)
(declare (ignorable k))
(not-to-be v)) self))
(:method ((self model-object))
(setf (md-census-count self) -1)
(md-quiesce self))
(:method :before ((self model-object))
(loop for slot-name in (md-owning-slots self)
do (not-to-be (slot-value self slot-name))))
(:method :around ((self model-object))
(declare (ignorable self))
(let ((*not-to-be* t)
(dbg nil))
(flet ((gok ()
(if (eq (md-state self) :eternal-rest)
(trc nil "n2be already dead" self)
(setf (fm-parent self) nil
(md-state self) :eternal-rest)
;;; (bif (a (assoc (type-of self) *awake-ct*))
;;; (decf (cdr a))
;;; (break "no awake for" (type-of self) *awake-ct*))
;;; (setf *awake* (delete self *awake*))
(md-map-cells self nil
(lambda (c)
(c-assert (eq :quiesced (c-state c)) ()
"Cell ~a of dead model ~a not quiesced. Was not-to-be shadowed by
a primary method? Use :before instead." c self))) ;; fails if user obstructs with primary method (use :before etc)
(if (not dbg)
(wtrc (0 100 " nailing" self (when (typep self 'family)
(mapcar 'type-of (slot-value self '.kids))))
(when dbg (trc "finished nailing" self))))))))
(defun md-quiesce (self)
(trc nil "md-quiesce nailing cells" self (type-of self))
(md-map-cells self nil (lambda (c)
(trc nil "quiescing" c)
(c-assert (not (find c *call-stack*)))
(c-quiesce c)))
(when (register? self)
(fm-check-out self)))
(defun c-quiesce (c)
(typecase c
(trc nil "c-quiesce unlinking" c)
(c-unlink-from-used c)
(dolist (caller (c-callers c))
(setf (c-value-state caller) :uncurrent)
(trc nil "c-quiesce totlalaly unlinking caller and making uncurrent" .dpid :q c :caller caller)
(c-unlink-caller c caller))
(setf (c-state c) :quiesced) ;; 20061024 for debugging for now, might break some code tho
(defparameter *to-be-dbg* nil)
(defmacro make-kid (class &rest initargs)
`(make-instance ,class
:fm-parent (progn (assert self) self)))
(defvar *c-d-d*)
(defvar *max-d-d*)
(defparameter *model-pop* nil)
(export! md-census-start md-census-report md-census-count)
(defun md-census-start ()
(setf *model-pop* (make-hash-table :test 'eq)))
(defun (setf md-census-count) (delta self)
(when *model-pop*
(incf (gethash (type-of self) *model-pop* 0) delta)))
(defun md-census-report ()
(when *model-pop*
(loop for (ct . type)
in (sort (let (raw)
(maphash (lambda (k v)
(push (cons v k) raw))
raw) '< :key 'car)
unless (zerop ct)
do (trc "pop" ct type))))
(defun md-census-count (&optional type)
(when *model-pop*
(if type
(gethash type *model-pop* 0)
(loop for v being the hash-values of *model-pop*
summing v))))
(defun count-model (self &key count-cells &aux (ccc 0))
(setf *c-d-d* (make-hash-table :test 'eq) *max-d-d* 0)
(let ((*counted* (make-hash-table :test 'eq :size 5000)))
(with-metrics (t nil "cells statistics for" self)
(labels ((cc (self from)
(unless (gethash self *counted*)
(setf (gethash self *counted*) t)
(typecase self
(cons (cc (car self) from)
(cc (cdr self) from))
#+nahhhh (mathx::box (count-it! :mathx-box-struct)
(cc (mathx::bx-mx self) from))
(when (zerop (mod (incf ccc) 100))
(trc "cc" (md-name self) (type-of self)))
(count-it! :thing)
(count-it! :thing (type-of self))
#+nahhhh (when (typep self 'mathx::problem)
(count-it! :thing-from (type-of self) (type-of from)))
(when count-cells
(loop for (nil . c) in (cells self)
do (count-it! :live-cell)
;(count-it! :live-cell id)
(when (c-lazy c)
(count-it! :lazy)
(count-it! :lazy (c-value-state c)))
(typecase c
(count-it! :dependent-cell)
#+chill (loop repeat (length (c-useds c))
do (count-it! :cell-useds)
(count-it! :dep-depth (c-depend-depth c))))
(otherwise (if (c-inputp c)
(count-it! :c-input-altogether)
;(count-it! :c-input id)
(count-it! :c-unknown))))
(loop repeat (length (c-callers c))
do (count-it! :cell-callers)))
(loop repeat (length (cells-flushed self))
do (count-it! :flushed-cell #+toomuchinfo id)))
(loop for slot in (md-owning-slots self) do
(loop for k in (let ((sv (SLOT-VALUE self slot)))
(if (listp sv) sv (list sv)))
do (cc k self)))
(when (typep self 'mathx::mx-optr)
(cc (mathx::opnds self) from))
(when (typep self 'mathx::math-expression)
(count-it! :math-expression))))
(count-it (type-of self)))))))
(cc self nil)))))
(defun c-depend-depth (ctop)
(if (null (c-useds ctop))
(or (gethash ctop *c-d-d*)
(labels ((cdd (c &optional (depth 1) chain)
(when (and (not (c-useds c))
(> depth *max-d-d*))
(setf *max-d-d* depth)
(trc "new dd champ from user" depth :down-to c)
(when (= depth 41)
(trc "end at" (c-slot-name c) :of (type-of (c-model c)))
(loop for c in chain do
(trc "called by" (c-slot-name c) :of (type-of (c-model c))))))
(setf (gethash c *c-d-d*)
;(break "c-depend-depth ~a" c)
;(trc "dd" c)
(1+ (loop for u in (c-useds c)
maximizing (cdd u (1+ depth) (cons c chain))))))))
(cdd ctop)))))