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

Contents of /freeable.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (hide annotations)
Sat Dec 22 19:24:45 2012 UTC (15 months, 3 weeks ago) by rklochkov
File size: 4539 byte(s)
Fixed array. Removed redefinition of cffi:mem-ref
1 rklochkov 13 ;;;;<author>Roman Klochkov, monk@slavsoft.surgut.ru</author>
2     ;;;; Base classes for freeable and changeable CFFI types
3 rklochkov 1
4 rklochkov 13 (in-package #:cffi-objects)
5 rklochkov 1
6 rklochkov 13 ;;;[ [[* 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 rklochkov 1 (define-foreign-type freeable-base ()
36 rklochkov 13 ;; Should we free after translating from foreign?
37     ((free-from-foreign :initarg :free-from-foreign
38 rklochkov 8 :reader fst-free-from-foreign-p
39     :initform nil :type boolean)
40     ;; Should we free after translating to foreign?
41 rklochkov 13 (free-to-foreign :initarg :free-to-foreign
42     :reader fst-free-to-foreign-p
43     :initform t :type boolean)))
44 rklochkov 1
45 rklochkov 13 #|<doc>
46     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 rklochkov 8
52 rklochkov 13 ;;;[ <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 rklochkov 1 (defgeneric free-ptr (type ptr)
71 rklochkov 5 (:documentation "Called to free ptr, unless overriden free-sent-ptr
72 rklochkov 9 or free-returned-ptr. TYPE should be specialized with EQL")
73 rklochkov 13 (:method (type ptr) (foreign-free ptr)))
74 rklochkov 1
75 rklochkov 13 ;;;[ <generic free-sent-ptr>
76    
77 rklochkov 9 (defgeneric free-sent-ptr (cffi-type ptr param)
78     (:method ((cffi-type freeable-base) ptr param)
79 rklochkov 4 (unless (null-pointer-p ptr)
80 rklochkov 9 (free-ptr (type-of cffi-type) ptr))))
81 rklochkov 1
82 rklochkov 13 ;;;[ <generic free-returned-ptr>
83    
84 rklochkov 9 (defgeneric free-returned-ptr (cffi-type ptr)
85     (:method ((cffi-type freeable-base) ptr)
86 rklochkov 4 (unless (null-pointer-p ptr)
87 rklochkov 9 (free-ptr (type-of cffi-type) ptr))))
88 rklochkov 1
89 rklochkov 13 ;;;[ <function free-sent-if-needed
90    
91 rklochkov 9 (defun free-sent-if-needed (cffi-type ptr param)
92     (when (fst-free-to-foreign-p cffi-type)
93     (free-sent-ptr cffi-type ptr param)))
94 rklochkov 1
95 rklochkov 13 ;;;[ <function free-returned-if-needed
96    
97 rklochkov 9 (defun free-returned-if-needed (cffi-type ptr)
98     (when (fst-free-from-foreign-p cffi-type)
99     (free-returned-ptr cffi-type ptr)))
100 rklochkov 1
101 rklochkov 13 ;;;[ <class freeable>
102    
103 rklochkov 1 (defclass freeable (freeable-base) ()
104     (:documentation "Mixing to auto-set translators"))
105    
106 rklochkov 13
107    
108 rklochkov 1 (defmethod free-translated-object :after (ptr (type freeable) param)
109 rklochkov 5 (free-sent-if-needed type ptr param))
110 rklochkov 1
111     (defmethod translate-from-foreign :after (ptr (type freeable))
112     (free-returned-if-needed type ptr))
113    
114 rklochkov 13 ;;;[ <class freeable-out>
115    
116 rklochkov 1 (define-foreign-type freeable-out (freeable)
117 rklochkov 12 ((out :accessor object-out :initarg :out :initform nil
118 rklochkov 1 :documentation "This is out param (for fill in foreign side)"))
119     (:documentation "For returning data in out params.
120 rklochkov 12 If OUT is t, then translate-to-foreign MUST return (values ptr place)"))
121 rklochkov 1
122     (defgeneric copy-from-foreign (type ptr place)
123     (:documentation "Transfers data from pointer PTR to PLACE"))
124    
125     (defmethod free-translated-object :before (ptr (type freeable-out) place)
126     (when (object-out type)
127     (copy-from-foreign type ptr place)))

  ViewVC Help
Powered by ViewVC 1.1.5