>>>>> On Mon, 09 May 2011 16:46:20 +0200, nitralime said: > > On 05/09/2011 01:49 PM, Martin Simmons wrote: > >>>>>> On Sun, 08 May 2011 14:39:41 +0200, Nitralime said: > >> Using a finalizer seems to be a possible way to go. But I'm not sure how > >> this can be done by just using the finalizer parameters "object" and > >> "function" > >> where "function" can't reliablely access "object" (cf. documentation of > >> finalizer > >> in "trivial-garbage" package)!! > >> > >> Any help and feedback is very much appreciated! > > IMHO, attempting to transparently wrap a foreign object with a CLOS object > > is > > not a good design. > > > > Using a finalizer is dangerous because it is difficult to guarantee that the > > Lisp wrapper object is retained for the correct lifetime. > > > > For example, consider > > > > (defstruct table > > foreign-pointer) > > > > (defun allocate-table () > > (make-table :foreign-pointer (foreign-allocate-table))) > > > > (defun allocate-and-munge-table () > > (let ((table (allocate-table))) > > (foreign-munge-table (table-foreign-pointer table)))) > > > > The compiler might not keep the variable "table" alive during the call to > > the > > foreign function foreign-munge-table. As a result, the Lisp table object > > might be gc'ed in another thread while the foreign code is accessing it. > > > Consider the following sample (pseudo-)code: > ---------------------------------------------------------- > (defclass table () > ((table-pointer :initarg :handle :accessor handle-of))) > > (defmethod initialize-instance :after ((self table) &key) > (let ((table-pointer (handle-of self))) > (tg:finalize self (lambda () (foreign-destroy-table table-pointer))))) > > (defmethod get-row ((t table) index) > (transform-to-lisp-vector (foreign-get-row (hadle-of t) index))) > > (defmethod move-to ((t table) index) > (foreign-move-to (handle-of t) index)) > ..... > ---------------------------------------------------------- > > Now consider a function which creates a table instance > and puts it into a result plist (and has probabely some side effects): > > (defun call-a-foreign-function (.....) > (let (....) > .... > <call a foreign function which allocates a table object > and returns a-foreign-table-pointer> > .... > (let ((result-table (make-instance 'table :handle a-foreign-table-pointer)) > (...)) > ... > ... > '(:id ... > :tab result-table > :msg ... > ...)))) > > The question is now what will happen if you do just > > (call-a-foreign-function ...) > > or something like this > > (getf (call-a-foreign-function ...) :id) > > I assume that the unreachable object 'result-table' will be garbage > collected, > and the finalization will free the corresponding C table object! > > Do you see any misconception (resp. potential danger) here?
Your examples will be safe, but (get-row (getf (call-a-foreign-function ...) :tab) 0) might crash. -- Martin Simmons LispWorks Ltd http://www.lispworks.com/ _______________________________________________ cffi-devel mailing list cffi-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/cffi-devel