Best way to do GC in Lisp/CFFI

Discussion of Common Lisp
Post Reply
joeish80829
Posts: 153
Joined: Tue Sep 03, 2013 5:32 am

Best way to do GC in Lisp/CFFI

Post by joeish80829 » Wed Apr 09, 2014 8:43 pm

I have Lisp functions that wrap C wrappers for C++ functions that contain a new operator. The C wrappers have to stay the same I can't change those but I was advised to update my method of GC.

Here are the C wrappers:

Code: Select all

Mat* cv_create_Mat() {
    return new Mat();
}

Code: Select all

void cv_delete_Mat(void* ptr) {
    delete (~Mat*)ptr;
}
Here are the Lisp wrappers for them:

Code: Select all

(defcfun ("cv_create_Mat" mat) (:pointer mat)
  "MAT constructor")


(defcfun ("cv_delete_Mat" del-mat) :void
  (ptr :pointer)) 
In a loop, as below, I would normally after calling a MAT function, delete it when I'm done with it manually with DEL-MAT, but I heard there was a better way by actually entering in the DEL-MAT function into Lisps natural GC methods so it would know when it comes across a function with a new it should call delete to get rid of it when it know i'm done with it.. The thing is I could use help to get started. Hopefully a concrete example of how to do this so I don't have to call DEL-MAT manually

Code: Select all

(dotimes (n 1000)
(setf m (mat))
(del-mat m))

marcoxa
Posts: 85
Joined: Thu Aug 14, 2008 6:31 pm

Re: Best way to do GC in Lisp/CFFI

Post by marcoxa » Thu Apr 10, 2014 12:11 pm

Another way to do it (gc on the C++ side) is to link in the Bohem GC and stop worrying. http://www.hboehm.info/gc/

Cheers
--
MA
Marco Antoniotti

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: Best way to do GC in Lisp/CFFI

Post by nuntius » Thu Apr 10, 2014 3:52 pm

You probably heard about "finalizers".
Here's a couple top links on the subject.

http://pinterface.livejournal.com/40614.html
https://github.com/Balooga/Simple-Finalizer

Finalizers involve some interesting tradeoffs.
C/C++ libraries are often written assuming strict, often lexically-scoped object lifecycles.
Finalizers hook into looser GC semantics.
The order of invocation is undefined for finalizers, and the GC may not even call them before program exit.
I'm undecided whether finalizers are a net win, but they definitely have some proponents.

joeish80829
Posts: 153
Joined: Tue Sep 03, 2013 5:32 am

Re: Best way to do GC in Lisp/CFFI

Post by joeish80829 » Fri Apr 11, 2014 10:07 am

Thanks for your replies to my question, I was planning to go the trivial-garbage route and someone from CFFI-DEVEL kindly gave me this code to do GC automatically using my mat and del-mat functions

Code: Select all

 (defstruct (cvmatrix (:constructor %make-cvmatrix))
  (sap (mat) :type sb-sys:system-area-pointer :read-only t))

 (defun make-cvmatrix ()
  (let* ((matrix (%make-cvmatrix))
          (sap (cvmatrix-sap matrix)))
    (tg:finalize matrix (lambda (x) (del-mat sap)))
    matrix))
When I run the make-cvmatrix function to create a matrix it outputs a struct instead of a pointer like i needed. I changed the last line of the make-cvmatrix function to be "sap" as below:

Code: Select all

    (tg:finalize matrix (lambda (x) (del-mat sap)))
    sap))
...and it appears to run fine with only minor variations in my ram levels which i suppose is just a result of lisps GC in process.
Since I'm new to GC w/ trivial-garbage, I was hoping someone can verify first that the change to sap was an ok move.

I was hoping someone could edit my code so I have a good example of Lisp GC with TG to work from and if I write a defcfun for this C wrapper :

Code: Select all

Mat* cv_create_Mat_typed(int rows, int cols, int type) {
    return new Mat(rows, cols, type);
}

eg:


(defcfun ("cv_create_Mat_typed" mat-typed)  (:pointer mat)
  "MAT constructor with a row, column and type parameter."
  (rows :int)
  (cols :int)
  (type :int))
show me where the rows cols type params get placed in an edited finalizer/constructor above..I would definately appreciate greatly:), concrete examples using the code I posted.

Post Reply