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

Contents of /freeable.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (show 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 ;;;;<author>Roman Klochkov, monk@slavsoft.surgut.ru</author>
2 ;;;; Base classes for freeable and changeable CFFI types
3
4 (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 ()
36 ;; Should we free after translating from foreign?
37 ((free-from-foreign :initarg :free-from-foreign
38 :reader fst-free-from-foreign-p
39 :initform nil :type boolean)
40 ;; Should we free after translating to foreign?
41 (free-to-foreign :initarg :free-to-foreign
42 :reader fst-free-to-foreign-p
43 :initform t :type boolean)))
44
45 #|<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
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)
71 (:documentation "Called to free ptr, unless overriden free-sent-ptr
72 or free-returned-ptr. TYPE should be specialized with EQL")
73 (:method (type ptr) (foreign-free ptr)))
74
75 ;;;[ <generic free-sent-ptr>
76
77 (defgeneric free-sent-ptr (cffi-type ptr param)
78 (:method ((cffi-type freeable-base) ptr param)
79 (unless (null-pointer-p ptr)
80 (free-ptr (type-of cffi-type) ptr))))
81
82 ;;;[ <generic free-returned-ptr>
83
84 (defgeneric free-returned-ptr (cffi-type ptr)
85 (:method ((cffi-type freeable-base) ptr)
86 (unless (null-pointer-p ptr)
87 (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)
92 (when (fst-free-to-foreign-p cffi-type)
93 (free-sent-ptr cffi-type ptr param)))
94
95 ;;;[ <function free-returned-if-needed
96
97 (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
101 ;;;[ <class freeable>
102
103 (defclass freeable (freeable-base) ()
104 (:documentation "Mixing to auto-set translators"))
105
106
107
108 (defmethod free-translated-object :after (ptr (type freeable) param)
109 (free-sent-if-needed type ptr param))
110
111 (defmethod translate-from-foreign :after (ptr (type freeable))
112 (free-returned-if-needed type ptr))
113
114 ;;;[ <class freeable-out>
115
116 (define-foreign-type freeable-out (freeable)
117 ((out :accessor object-out :initarg :out :initform nil
118 :documentation "This is out param (for fill in foreign side)"))
119 (:documentation "For returning data in out params.
120 If OUT is t, then translate-to-foreign MUST return (values ptr place)"))
121
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