-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathallocator.lisp
85 lines (76 loc) · 5.64 KB
/
allocator.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
(in-package #:cffi-object)
(declaim (inline make-cobject-allocator))
(defstruct cobject-allocator
(allocator (constantly (cffi:null-pointer)) :type (function (cffi::foreign-type) (values cffi:foreign-pointer)))
(deallocator #'values :type (function (cffi:foreign-pointer))))
(declaim (type cobject-allocator *default-cobject-allocator*))
(defparameter *default-cobject-allocator* (make-cobject-allocator
:allocator (lambda (type) (cffi-sys:%foreign-alloc (cffi:foreign-type-size type)))
:deallocator #'cffi-sys:foreign-free))
(declaim (type cobject-allocator *cobject-allocator*))
(defparameter *cobject-allocator* *default-cobject-allocator*)
(declaim (inline make-leaky-allocator))
(defun make-leaky-allocator (&key (allocator (cobject-allocator-allocator *cobject-allocator*)) (deallocator #'values))
(make-cobject-allocator :allocator allocator :deallocator deallocator))
(defmacro with-leaky-allocator (&body body)
(with-gensyms (allocator)
`(let ((,allocator (make-leaky-allocator)))
(declare (dynamic-extent ,allocator))
(let ((*cobject-allocator* ,allocator)) . ,body))))
(declaim (inline %make-sized-monotonic-buffer-allocator))
(defstruct (sized-monotonic-buffer-allocator (:include cobject-allocator) (:constructor %make-sized-monotonic-buffer-allocator))
(pointer (cffi:null-pointer) :type cffi:foreign-pointer)
(size 0 :type non-negative-fixnum)
(offset 0 :type non-negative-fixnum))
(declaim (inline make-sized-monotonic-buffer-allocator))
(defun make-sized-monotonic-buffer-allocator (&key (pointer (cffi:null-pointer)) (size 0) (upstream *cobject-allocator*))
#+sbcl (declare (sb-ext:muffle-conditions sb-ext:compiler-note))
(let* ((allocator-1 nil)
(allocator-2 (%make-sized-monotonic-buffer-allocator :allocator (lambda (type &aux (size (cffi:foreign-type-size type)) (align (cffi:foreign-type-alignment type)))
(declare (type non-negative-fixnum size align))
(with-accessors ((offset sized-monotonic-buffer-allocator-offset)
(buffer-size sized-monotonic-buffer-allocator-size)
(pointer sized-monotonic-buffer-allocator-pointer)
(allocator sized-monotonic-buffer-allocator-allocator)
(deallocator sized-monotonic-buffer-allocator-deallocator))
allocator-1
(let ((align-offset (mod (- align offset) align)))
(if (<= (+ offset align-offset size) buffer-size)
(prog1 (cffi:inc-pointer pointer (incf offset align-offset))
(incf offset size))
(if upstream
(prog1 (funcall (cobject-allocator-allocator upstream) type)
(setf offset buffer-size)
(setf deallocator (cobject-allocator-deallocator upstream)))
(error "Cannot allocate a space of ~D byte~:P with allocator ~A." size allocator-1))))))
:deallocator #'values :size size :pointer pointer)))
(setf allocator-1 allocator-2)
allocator-2))
(defmacro with-monotonic-buffer-allocator ((&key
buffer pointer
(size (if buffer `(length ,buffer) 128))
(upstream '*cobject-allocator*)
(values '#'values))
&body body)
(with-gensyms (buffer-var pointer-var size-var allocator)
(flet ((wrap-with-buffer-var (form)
(cond
(buffer `(let ((,buffer-var ,buffer)) ,form))
(pointer form)
(t `(let ((,buffer-var (cffi:make-shareable-byte-vector ,size-var)))
(declare (dynamic-extent ,buffer-var)) ,form))))
(wrap-with-pointer-var (form)
(if pointer
`(let ((,pointer-var ,pointer)) ,form)
`(cffi:with-pointer-to-vector-data (,pointer-var ,buffer-var) ,form))))
`(let ((,size-var ,size))
,(wrap-with-buffer-var
(wrap-with-pointer-var
`(let ((,allocator (make-sized-monotonic-buffer-allocator :pointer ,pointer-var :size ,size-var :upstream ,upstream)))
(declare (dynamic-extent ,allocator))
(multiple-value-call ,values
(let ((*cobject-allocator* ,allocator))
,@body)))))))))
(defmacro with-default-allocator (&body body)
`(let ((*cobject-allocator* *default-cobject-allocator*))
,@body))