0.8.21.31: tweak finalizers, thighten spec further
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 10 Apr 2005 12:55:54 +0000 (12:55 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 10 Apr 2005 12:55:54 +0000 (12:55 +0000)
 * sprinkle WITHOUT-GCING around, so that we won't enter GC while
    holding the lock on finalizer store.
 * specify that finalizers run in an unpredictable dynamic scope and
    must be fully re-entrant. Add a few examples for good measure.
 * add finalizer, weak pointer, and after gc hook documentation to the
    manual.

NEWS
doc/manual/beyond-ansi.texinfo
src/code/final.lisp
src/code/weak.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index 041ea38..b85bd54 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,8 +6,10 @@ changes in sbcl-0.8.22 relative to sbcl-0.8.21:
     interrupts enabled.
   * incompatible change: support for *BEFORE-GC-HOOKS* (that have been
     inoperational for a while now) has been completely removed.
     interrupts enabled.
   * incompatible change: support for *BEFORE-GC-HOOKS* (that have been
     inoperational for a while now) has been completely removed.
-  * Null lexical environments are now printed as #<NULL-LEXENV>, 
+  * null lexical environments are now printed as #<NULL-LEXENV>, 
     significantly reducing the amount of clutter in typical backtraces.
     significantly reducing the amount of clutter in typical backtraces.
+  * documentation on weak pointers, finalization, and after GC hooks
+    has been added to the manual.
   * optimization: REPLACE on declared (UNSIGNED-BYTE 8) vectors, as well
     as other specialized array types, is much faster.  SUBSEQ and
     COPY-SEQ on such arrays have also been sped up.
   * optimization: REPLACE on declared (UNSIGNED-BYTE 8) vectors, as well
     as other specialized array types, is much faster.  SUBSEQ and
     COPY-SEQ on such arrays have also been sped up.
index a0bffa2..4bb8556 100644 (file)
@@ -7,36 +7,38 @@ ANSI standard. SBCL doesn't support as many extensions as CMUCL, but
 it still has quite a few.  @xref{Contributed Modules}.
 
 @menu
 it still has quite a few.  @xref{Contributed Modules}.
 
 @menu
-* Things Which Might Be In The Next ANSI Standard::  
+* Garbage Collection::          
+* Metaobject Protocol::         
 * Support For Unix::            
 * Customization Hooks for Users::  
 * Tools To Help Developers::    
 * Support For Unix::            
 * Customization Hooks for Users::  
 * Tools To Help Developers::    
-* Resolution of Name Conflicts::
+* Resolution of Name Conflicts::  
 * Stale Extensions::            
 * Efficiency Hacks::            
 @end menu
 
 * Stale Extensions::            
 * Efficiency Hacks::            
 @end menu
 
-@node  Things Which Might Be In The Next ANSI Standard
+@node  Garbage Collection
 @comment  node-name,  next,  previous,  up
 @comment  node-name,  next,  previous,  up
-@section Things Which Might Be In The Next ANSI Standard
-
-SBCL provides extensive support for calling external C code,
-@ref{Foreign Function Interface}.
+@section Garbage Collection
 
 SBCL provides additional garbage collection functionality not
 specified by ANSI. Weak pointers allow references to objects to be
 
 SBCL provides additional garbage collection functionality not
 specified by ANSI. Weak pointers allow references to objects to be
-maintained without keeping them from being GCed (garbage
-collected). And ``finalization'' hooks are available to cause code to
-be executed when an object has been GCed.
-@c <!-- FIXME: Actually documenting these would be good.:-| -->
-
-SBCL supports @dfn{Gray streams}, user-overloadable CLOS classes whose
-instances can be used as Lisp streams (e.g. passed as the first
-argument to @code{format}).  Additionally, the bundled contrib module
-@dfn{sb-simple-streams} implements a subset of the Franz Allegro
-simple-streams proposal.
-
-SBCL supports a MetaObject Protocol which is intended to be compatible
+maintained without keeping them from being garbage collected, and
+``finalization'' hooks are available to cause code to be executed when
+an object has been garbage collected. Additionally users can specify
+their own cleanup actions to be executed with garbage collection.
+
+@include fun-sb-ext-finalize.texinfo
+@include fun-sb-ext-cancel-finalization.texinfo
+@include fun-sb-ext-make-weak-pointer.texinfo
+@include fun-sb-ext-weak-pointer-value.texinfo
+@include var-sb-ext-star-after-gc-hooks-star.texinfo
+
+@node Metaobject Protocol
+@comment  node-name,  next,  previous,  up
+@section Metaobject Protocol
+
+SBCL supports a metaobject protocol which is intended to be compatible
 with AMOP; present exceptions to this (as distinct from current bugs)
 are:
 
 with AMOP; present exceptions to this (as distinct from current bugs)
 are:
 
index a2adcaf..945cd5e 100644 (file)
 (defun finalize (object function)
   #!+sb-doc 
   "Arrange for the designated FUNCTION to be called when there
 (defun finalize (object function)
   #!+sb-doc 
   "Arrange for the designated FUNCTION to be called when there
-are no more references to OBJECT. In a multithreaded environment
-the finalizer may run in any thread."
-  (sb!thread:with-mutex (*finalizer-store-lock*)
-    (push (cons (make-weak-pointer object) function)
-         *finalizer-store*))
+are no more references to OBJECT, including references in
+FUNCTION itself.
+
+In a multithreaded environment FUNCTION may be called in any
+thread. In both single and multithreaded environments FUNCTION
+may be called in any dynamic scope: consequences are unspecified
+if FUNCTION is not fully re-entrant.
+
+Errors from FUNCTION are handled and cause a WARNING to be
+signalled in whichever thread the FUNCTION was called in.
+
+Examples:
+
+  ;;; good
+  (let* ((handle (get-handle))
+         (object (make-object handle)))
+   ;; assumes RELEASE-HANDLE is re-entrant
+   (finalize object (lambda () (release-handle handle)))
+   object)
+
+  ;;; bad, finalizer refers to object being finalized, causing
+  ;;; it to be retained indefinitely
+  (let* ((handle (get-handle))
+         (object (make-object handle)))
+    (finalize object (lambda () (release-handle (object-handle object)))))
+
+  ;;; bad, not re-entrant
+  (defvar *rec* nil)
+
+  (defun oops ()
+   (when *rec* 
+     (error \"recursive OOPS\"))
+   (let ((*rec* t))
+     (gc))) ; or just cons enough to cause one
+
+  (progn 
+    (finalize \"oops\" #'oops)
+    (oops)) ; causes GC and re-entry to #'oops due to the finalizer
+            ; -> ERROR, caught, WARNING signalled"
+  (sb!sys:without-gcing
+      (sb!thread:with-mutex (*finalizer-store-lock*)
+       (push (cons (make-weak-pointer object) function)
+             *finalizer-store*)))
   object)
 
 (defun cancel-finalization (object)
   object)
 
 (defun cancel-finalization (object)
@@ -32,22 +70,24 @@ the finalizer may run in any thread."
   ;; Check for NIL to avoid deleting finalizers that are waiting to be
   ;; run.
   (when object
   ;; Check for NIL to avoid deleting finalizers that are waiting to be
   ;; run.
   (when object
-    (sb!thread:with-mutex (*finalizer-store-lock*)
-      (setf *finalizer-store*
-           (delete object *finalizer-store*
-                   :key (lambda (pair) 
-                          (weak-pointer-value (car pair))))))
+    (sb!sys:without-gcing
+       (sb!thread:with-mutex (*finalizer-store-lock*)
+         (setf *finalizer-store*
+               (delete object *finalizer-store*
+                       :key (lambda (pair) 
+                              (weak-pointer-value (car pair)))))))
     object))
 
 (defun run-pending-finalizers ()
   (let (pending)
     object))
 
 (defun run-pending-finalizers ()
   (let (pending)
-    (sb!thread:with-mutex (*finalizer-store-lock*)
-      (setf *finalizer-store*
-           (delete-if  (lambda (pair)
-                         (when (null (weak-pointer-value (car pair)))
-                           (push (cdr pair) pending)
-                           t))
-                     *finalizer-store*)))
+    (sb!sys:without-gcing
+       (sb!thread:with-mutex (*finalizer-store-lock*)
+         (setf *finalizer-store*
+               (delete-if  (lambda (pair)
+                             (when (null (weak-pointer-value (car pair)))
+                               (push (cdr pair) pending)
+                               t))
+                           *finalizer-store*))))
     ;; We want to run the finalizer bodies outside the lock in case
     ;; finalization of X causes finalization to be added for Y.
     (dolist (fun pending)
     ;; We want to run the finalizer bodies outside the lock in case
     ;; finalization of X causes finalization to be added for Y.
     (dolist (fun pending)
index 37b83a1..7268b38 100644 (file)
 (defun make-weak-pointer (object)
   #!+sb-doc
   "Allocate and return a weak pointer which points to OBJECT."
 (defun make-weak-pointer (object)
   #!+sb-doc
   "Allocate and return a weak pointer which points to OBJECT."
-  (declare (values weak-pointer))
   (make-weak-pointer object))
 
 #!-sb-fluid (declaim (inline weak-pointer-value))
 (defun weak-pointer-value (weak-pointer)
   #!+sb-doc
   "If WEAK-POINTER is valid, return the value of WEAK-POINTER and T.
   (make-weak-pointer object))
 
 #!-sb-fluid (declaim (inline weak-pointer-value))
 (defun weak-pointer-value (weak-pointer)
   #!+sb-doc
   "If WEAK-POINTER is valid, return the value of WEAK-POINTER and T.
-   If the referent of WEAK-POINTER has been garbage collected, returns
-   the values NIL and NIL."
-  (declare (type weak-pointer weak-pointer)
-          (values t (member t nil)))
+If the referent of WEAK-POINTER has been garbage collected,
+returns the values NIL and NIL."
+  (declare (type weak-pointer weak-pointer))
   ;; We don't need to wrap this with a WITHOUT-GCING, because once we
   ;; have extracted the value, our reference to it will keep the weak
   ;; pointer from becoming broken. We just have to make sure the
   ;; We don't need to wrap this with a WITHOUT-GCING, because once we
   ;; have extracted the value, our reference to it will keep the weak
   ;; pointer from becoming broken. We just have to make sure the
index a795dd1..c29142b 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.21.30"
+"0.8.21.31"