1 ;;;; finalization based on weak pointers
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!IMPL")
14 (defvar *finalizer-store* nil)
16 (defvar *finalizer-store-lock*
17 (sb!thread:make-mutex :name "Finalizer store lock."))
19 (defun finalize (object function)
21 "Arrange for the designated FUNCTION to be called when there
22 are no more references to OBJECT, including references in
25 In a multithreaded environment FUNCTION may be called in any
26 thread. In both single and multithreaded environments FUNCTION
27 may be called in any dynamic scope: consequences are unspecified
28 if FUNCTION is not fully re-entrant.
30 Errors from FUNCTION are handled and cause a WARNING to be
31 signalled in whichever thread the FUNCTION was called in.
35 ;;; good (assumes RELEASE-HANDLE is re-entrant)
36 (let* ((handle (get-handle))
37 (object (make-object handle)))
38 (finalize object (lambda () (release-handle handle)))
41 ;;; bad, finalizer refers to object being finalized, causing
42 ;;; it to be retained indefinitely
43 (let* ((handle (get-handle))
44 (object (make-object handle)))
45 (finalize object (lambda () (release-handle (object-handle object)))))
47 ;;; bad, not re-entrant
52 (error \"recursive OOPS\"))
54 (gc))) ; or just cons enough to cause one
57 (finalize \"oops\" #'oops)
58 (oops)) ; causes GC and re-entry to #'oops due to the finalizer
59 ; -> ERROR, caught, WARNING signalled"
61 (sb!thread:with-mutex (*finalizer-store-lock*)
62 (push (cons (make-weak-pointer object) function)
66 (defun cancel-finalization (object)
68 "Cancel any finalization for OBJECT."
69 ;; Check for NIL to avoid deleting finalizers that are waiting to be
73 (sb!thread:with-mutex (*finalizer-store-lock*)
74 (setf *finalizer-store*
75 (delete object *finalizer-store*
77 (weak-pointer-value (car pair)))))))
80 (defun run-pending-finalizers ()
83 (sb!thread:with-mutex (*finalizer-store-lock*)
84 (setf *finalizer-store*
85 (delete-if (lambda (pair)
86 (when (null (weak-pointer-value (car pair)))
87 (push (cdr pair) pending)
90 ;; We want to run the finalizer bodies outside the lock in case
91 ;; finalization of X causes finalization to be added for Y.
96 (warn "Error calling finalizer ~S:~% ~S" fun c)))))