/[cffi-objects]/freeable.lisp
ViewVC logotype

Diff of /freeable.lisp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 12 by rklochkov, Sun Oct 7 11:59:54 2012 UTC revision 13 by rklochkov, Sat Dec 22 19:24:45 2012 UTC
# Line 1  Line 1 
1  ;;;; -*- Mode: lisp -*-  ;;;;<author>Roman Klochkov, monk@slavsoft.surgut.ru</author>
2  ;;;  ;;;; Base classes for freeable and changeable CFFI types
 ;;; freeable.lisp --- Interface for objects, that may be freed after use  
 ;;;  
 ;;; Copyright (C) 2011, Roman Klochkov <kalimehtar@mail.ru>  
 ;;;  
3    
4  (in-package #:cffi-objects)  (in-package #:cffi-objects)
5    
6    ;;;[ [[* Memory freeing automation *]]
7    
8    #|<doc>
9    Most of new CFFI types introduced in my library will live in the dynamic
10    memory. There are different policies of memory control in different languages
11    and libraries. Sometimes caller should clean memory (like in GTK), sometimes
12    callee.
13    
14    In any case programmer should have possibility to say, if he would
15    like to free memory after function call. For example, in GTK it is common
16    for callback to return a newly-allocated string or structure, but in
17    parameters responsibility to clean memory remains to caller.
18    
19    Another common option for any type is a flag, that it is out-paramter,
20    so value of it should be translated back before freeing,
21    
22    For uniformity with CFFI :string I chose :free-from-foreign and
23    :free-to-foreign boolean flags to show, when we want to free memory. By default
24    "caller frees" model is used.
25    |#
26    
27    ;;;[ <class freeable-base>
28    
29    #|<doc> I divided freeable functional to two classes:
30    \begin{itemize}
31    \item [[freeable-base]] introduces all necessary fields and handlers
32    \item [[freeable]] have ready cffi-translator methods
33    |#
34    
35  (define-foreign-type freeable-base ()  (define-foreign-type freeable-base ()
36     ;; Should we free after translating from foreign?    ;; Should we free after translating from foreign?
37     ((free-from-foreign :initarg :free-from-foreign    ((free-from-foreign :initarg :free-from-foreign
38                        :reader fst-free-from-foreign-p                        :reader fst-free-from-foreign-p
39                        :initform nil :type boolean)                        :initform nil :type boolean)
40     ;; Should we free after translating to foreign?     ;; Should we free after translating to foreign?
41      (free-to-foreign :initarg :free-to-foreign     (free-to-foreign :initarg :free-to-foreign
42                       :reader fst-free-to-foreign-p                      :reader fst-free-to-foreign-p
43                       :initform t :type boolean)))                      :initform t :type boolean)))
44    
45  ;; You should call FREE-RETURNED-IF-NEEDED and FREE-SENT-IF-NEEDED in  #|<doc>
46  ;; appropriate places of your CFFI translators")))  Interface to [[freeable-base]] consists of three generics for describing,
47    how to free particular type: [[free-ptr]], [[free-sent-ptr]] and
48    [[free-returned-ptr]], and two functions to use in CFFI translators:
49    [[free-returned-if-needed]] and [[free-sent-if-needed]].
50    |#
51    
52    ;;;[ <generic free-ptr (type ptr)>
53    
54    #|<doc>
55    This generic describes, how to free an object with CFFI type [[type]] and
56    pointer [[ptr]]. As [[type]] should be a symbol, you should specialize
57    this generic with EQL specifier if your objects shouldn't be freed with
58    [[foreign-free].
59    
60    One can ask, why normal specializer by type of object and [[object] as
61    a first parameter is not used. Such strange API is developed,
62    because [[free-ptr]] is used in [[trivial-garbage:finalize]] and in some
63    implementation (for example, SBCL) finalizer shouldn't have reference
64    to finalized object.
65    
66    If you dislike it and you will not use finalizers, simply specialize or
67    redefine [[free-sent-ptr]] and [[free-returned-ptr]]
68    |#
69    
70  (defgeneric free-ptr (type ptr)  (defgeneric free-ptr (type ptr)
71    (:documentation "Called to free ptr, unless overriden free-sent-ptr    (:documentation "Called to free ptr, unless overriden free-sent-ptr
72  or free-returned-ptr. TYPE should be specialized with EQL")  or free-returned-ptr. TYPE should be specialized with EQL")
73    (:method (type ptr)    (:method (type ptr) (foreign-free ptr)))
74      (foreign-free ptr)))  
75    ;;;[ <generic free-sent-ptr>
76    
77  (defgeneric free-sent-ptr (cffi-type ptr param)  (defgeneric free-sent-ptr (cffi-type ptr param)
78    (:method ((cffi-type freeable-base) ptr param)    (:method ((cffi-type freeable-base) ptr param)
79      (unless (null-pointer-p ptr)      (unless (null-pointer-p ptr)
80        (free-ptr (type-of cffi-type) ptr))))        (free-ptr (type-of cffi-type) ptr))))
81    
82    ;;;[ <generic free-returned-ptr>
83    
84  (defgeneric free-returned-ptr (cffi-type ptr)  (defgeneric free-returned-ptr (cffi-type ptr)
85    (:method ((cffi-type freeable-base) ptr)    (:method ((cffi-type freeable-base) ptr)
86      (unless (null-pointer-p ptr)      (unless (null-pointer-p ptr)
87        (free-ptr (type-of cffi-type) ptr))))        (free-ptr (type-of cffi-type) ptr))))
88    
89    ;;;[ <function free-sent-if-needed
90    
91  (defun free-sent-if-needed (cffi-type ptr param)  (defun free-sent-if-needed (cffi-type ptr param)
92    (when (fst-free-to-foreign-p cffi-type)    (when (fst-free-to-foreign-p cffi-type)
93      (free-sent-ptr cffi-type ptr param)))      (free-sent-ptr cffi-type ptr param)))
94    
95    ;;;[ <function free-returned-if-needed
96    
97  (defun free-returned-if-needed (cffi-type ptr)  (defun free-returned-if-needed (cffi-type ptr)
98    (when (fst-free-from-foreign-p cffi-type)    (when (fst-free-from-foreign-p cffi-type)
99      (free-returned-ptr cffi-type ptr)))      (free-returned-ptr cffi-type ptr)))
100    
101    ;;;[ <class freeable>
102    
103  (defclass freeable (freeable-base) ()  (defclass freeable (freeable-base) ()
104    (:documentation "Mixing to auto-set translators"))    (:documentation "Mixing to auto-set translators"))
105    
106    
107    
108  (defmethod free-translated-object :after (ptr (type freeable) param)  (defmethod free-translated-object :after (ptr (type freeable) param)
109    (free-sent-if-needed type ptr param))    (free-sent-if-needed type ptr param))
110    
111  (defmethod translate-from-foreign :after (ptr (type freeable))  (defmethod translate-from-foreign :after (ptr (type freeable))
112    (free-returned-if-needed type ptr))    (free-returned-if-needed type ptr))
113    
114    ;;;[ <class freeable-out>
115    
116  (define-foreign-type freeable-out (freeable)  (define-foreign-type freeable-out (freeable)
117    ((out :accessor object-out :initarg :out :initform nil    ((out :accessor object-out :initarg :out :initform nil
118          :documentation "This is out param (for fill in foreign side)"))          :documentation "This is out param (for fill in foreign side)"))

Legend:
Removed from v.12  
changed lines
  Added in v.13

  ViewVC Help
Powered by ViewVC 1.1.5