X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/clg/blobdiff_plain/2bd78f93f681c3afb5b555265ae3831fbe3ba017..8f49b7a10a9717890ca98dff2b01799b80ce2761:/gffi/proxy.lisp diff --git a/gffi/proxy.lisp b/gffi/proxy.lisp index 9cf15ca..7ce9f05 100644 --- a/gffi/proxy.lisp +++ b/gffi/proxy.lisp @@ -20,7 +20,7 @@ ;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -;; $Id: proxy.lisp,v 1.4 2006-08-16 12:09:03 espen Exp $ +;; $Id: proxy.lisp,v 1.10 2007-12-11 14:26:11 espen Exp $ (in-package "GFFI") @@ -83,13 +83,14 @@ (defun list-invalidated-instances () ;;;; Proxy for alien instances -#+clisp -(defvar *foreign-instance-locations* (make-hash-table :weak :key)) +#?(or (sbcl>= 0 9 17) (featurep :clisp)) +(defvar *foreign-instance-locations* + (make-hash-table #+clisp :weak #+sbcl :weakness :key)) + -;; TODO: add a ref-counted-proxy subclass (eval-when (:compile-toplevel :load-toplevel :execute) (defclass proxy (virtual-slots-object) - (#-clisp(location :special t :type pointer)) + (#?-(or (sbcl>= 0 9 17) (featurep :clisp))(%location :special t :type pointer)) (:metaclass virtual-slots-class))) (defgeneric instance-finalizer (instance)) @@ -98,17 +99,28 @@ (defgeneric unreference-function (class)) (defgeneric invalidate-instance (instance &optional finalize-p)) (defgeneric allocate-foreign (object &key &allow-other-keys)) -(defun foreign-location (instance) - #-clisp(slot-value instance 'location) - #+clisp(gethash instance *foreign-instance-locations*)) +#?-(or (sbcl>= 0 9 17) (featurep :clisp)) +(progn + (defun foreign-location (instance) + (slot-value instance '%location)) + + (defun (setf foreign-location) (location instance) + (setf (slot-value instance '%location) location)) + + (defun proxy-valid-p (instance) + (slot-boundp instance '%location))) + +#?(or (sbcl>= 0 9 17) (featurep :clisp)) +(progn + (defun foreign-location (instance) + (gethash instance *foreign-instance-locations*)) + + (defun (setf foreign-location) (location instance) + (setf (gethash instance *foreign-instance-locations*) location)) -(defun (setf foreign-location) (location instance) - #-clisp(setf (slot-value instance 'location) location) - #+clisp(setf (gethash instance *foreign-instance-locations*) location)) + (defun proxy-valid-p (instance) + (and (gethash instance *foreign-instance-locations*) t))) -(defun proxy-valid-p (instance) - #-clisp(slot-boundp instance 'location) - #+clisp(and (gethash instance *foreign-instance-locations*) t)) (defmethod reference-function ((name symbol)) (reference-function (find-class name))) @@ -151,16 +163,18 @@ (defmethod instance-finalizer ((instance proxy)) #'(lambda () (funcall unref location)))) -;; FINALIZE-P should always be given the same value as the keyword -;; argument :FINALZIE given to MAKE-PROXY-INSTANCE or non NIL if the -;; proxy was created with MAKE-INSTANCE +;; FINALIZE-P should always be the same as the keyword argument +;; :FINALZIE given to MAKE-PROXY-INSTANCE or non NIL if the proxy was +;; created with MAKE-INSTANCE (defmethod invalidate-instance ((instance proxy) &optional finalize-p) + #+clisp(declare (ignore finalize-p)) (remove-cached-instance (foreign-location instance)) #+(or sbcl cmu) (progn (when finalize-p (funcall (instance-finalizer instance))) - (slot-makunbound instance 'location) + #?-(sbcl>= 0 9 17)(slot-makunbound instance '%location) + #?(sbcl>= 0 9 17)(remhash instance *foreign-instance-locations*) (cancel-finalization instance)) ;; We can't cache invalidated instances in CLISP beacuse it is ;; not possible to cancel finalization @@ -288,6 +302,8 @@ (defmethod compute-slot-writer-function ((slotd effective-virtual-alien-slot-d #'(lambda (value object) (unless writer (setq writer (mkbinding setter nil 'pointer type))) + ;; First argument in foreign setters is the object and second + ;; is value (funcall writer (foreign-location object) value))) (call-next-method))) @@ -486,6 +502,20 @@ (defmethod make-proxy-instance ((class proxy-class) location (cache-instance instance) instance)) +;;;; Superclass for ref-counted objects + +(defclass ref-counted-object (proxy) + () + (:metaclass proxy-class)) + +(define-type-method from-alien-form ((type ref-counted-object) form + &key (ref :copy)) + (call-next-method type form :ref ref)) + +(define-type-method from-alien-function ((type ref-counted-object) + &key (ref :copy)) + (call-next-method type :ref ref)) + ;;;; Superclasses for wrapping of C structures @@ -569,7 +599,7 @@ (defmethod compute-slots :around ((class struct-class)) (define-type-method callback-wrapper ((type struct) var arg form) (let ((class (type-expand type))) - `(let ((,var (ensure-proxy-instance ',class ,arg :finalize nil))) + `(let ((,var (ensure-proxy-instance ',class ,arg :reference nil :finalize nil))) (unwind-protect ,form (invalidate-instance ,var)))))