Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
90f19619
Commit
90f19619
authored
Jul 18, 2008
by
Dag Sverre Seljebotn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Buffers released at function exit
parent
68e1429c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
141 additions
and
22 deletions
+141
-22
Cython/Compiler/Buffer.py
Cython/Compiler/Buffer.py
+27
-5
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+11
-2
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+11
-0
tests/run/bufaccess.pyx
tests/run/bufaccess.pyx
+92
-15
No files found.
Cython/Compiler/Buffer.py
View file @
90f19619
...
@@ -97,12 +97,12 @@ class BufferTransform(CythonTransform):
...
@@ -97,12 +97,12 @@ class BufferTransform(CythonTransform):
# For all buffers, insert extra variables in the scope.
# For all buffers, insert extra variables in the scope.
# The variables are also accessible from the buffer_info
# The variables are also accessible from the buffer_info
# on the buffer entry
# on the buffer entry
bufvars
=
[
(
name
,
entry
)
for
name
,
entry
bufvars
=
[
entry
for
name
,
entry
in
scope
.
entries
.
iteritems
()
in
scope
.
entries
.
iteritems
()
if
entry
.
type
.
is_buffer
]
if
entry
.
type
.
is_buffer
]
for
name
,
entry
in
bufvars
:
for
entry
in
bufvars
:
name
=
entry
.
name
buftype
=
entry
.
type
buftype
=
entry
.
type
# Get or make a type string checker
# Get or make a type string checker
...
@@ -130,6 +130,7 @@ class BufferTransform(CythonTransform):
...
@@ -130,6 +130,7 @@ class BufferTransform(CythonTransform):
entry
.
buffer_aux
=
Symtab
.
BufferAux
(
bufinfo
,
stridevars
,
entry
.
buffer_aux
=
Symtab
.
BufferAux
(
bufinfo
,
stridevars
,
shapevars
,
tschecker
)
shapevars
,
tschecker
)
entry
.
buffer_aux
.
temp_var
=
temp_var
entry
.
buffer_aux
.
temp_var
=
temp_var
scope
.
buffer_entries
=
bufvars
self
.
scope
=
scope
self
.
scope
=
scope
# Notes: The cast to <char*> gets around Cython not supporting const types
# Notes: The cast to <char*> gets around Cython not supporting const types
...
@@ -223,10 +224,31 @@ class BufferTransform(CythonTransform):
...
@@ -223,10 +224,31 @@ class BufferTransform(CythonTransform):
return
result
return
result
buffer_cleanup_fragment
=
TreeFragment
(
u"""
if BUF is not None:
__cython__.PyObject_ReleaseBuffer(<__cython__.PyObject*>BUF, &BUFINFO)
"""
)
def
funcdef_buffer_cleanup
(
self
,
node
):
pos
=
node
.
pos
env
=
node
.
local_scope
cleanups
=
[
self
.
buffer_cleanup_fragment
.
substitute
({
u"BUF"
:
NameNode
(
pos
,
name
=
entry
.
name
),
u"BUFINFO"
:
NameNode
(
pos
,
name
=
entry
.
buffer_aux
.
buffer_info_var
.
name
)
})
for
entry
in
node
.
local_scope
.
buffer_entries
]
cleanup_stats
=
[]
for
c
in
cleanups
:
cleanup_stats
+=
c
.
stats
cleanup
=
StatListNode
(
pos
,
stats
=
cleanup_stats
)
cleanup
.
analyse_expressions
(
env
)
result
=
TryFinallyStatNode
.
create_analysed
(
pos
,
env
,
body
=
node
.
body
,
finally_clause
=
cleanup
)
node
.
body
=
result
return
node
#
#
# Transforms
# Transforms
#
#
def
visit_ModuleNode
(
self
,
node
):
def
visit_ModuleNode
(
self
,
node
):
self
.
handle_scope
(
node
,
node
.
scope
)
self
.
handle_scope
(
node
,
node
.
scope
)
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
...
@@ -235,7 +257,7 @@ class BufferTransform(CythonTransform):
...
@@ -235,7 +257,7 @@ class BufferTransform(CythonTransform):
def
visit_FuncDefNode
(
self
,
node
):
def
visit_FuncDefNode
(
self
,
node
):
self
.
handle_scope
(
node
,
node
.
local_scope
)
self
.
handle_scope
(
node
,
node
.
local_scope
)
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
return
node
return
self
.
funcdef_buffer_cleanup
(
node
)
def
visit_SingleAssignmentNode
(
self
,
node
):
def
visit_SingleAssignmentNode
(
self
,
node
):
# On assignments, two buffer-related things can happen:
# On assignments, two buffer-related things can happen:
...
...
Cython/Compiler/ExprNodes.py
View file @
90f19619
...
@@ -809,6 +809,13 @@ class NameNode(AtomicExprNode):
...
@@ -809,6 +809,13 @@ class NameNode(AtomicExprNode):
# interned_cname string
# interned_cname string
is_name
=
1
is_name
=
1
def
create_analysed_rvalue
(
pos
,
env
,
entry
):
node
=
NameNode
(
pos
)
node
.
analyse_types
(
env
,
entry
=
entry
)
return
node
create_analysed_rvalue
=
staticmethod
(
create_analysed_rvalue
)
def
compile_time_value
(
self
,
denv
):
def
compile_time_value
(
self
,
denv
):
try
:
try
:
...
@@ -862,8 +869,10 @@ class NameNode(AtomicExprNode):
...
@@ -862,8 +869,10 @@ class NameNode(AtomicExprNode):
if
self
.
entry
.
is_pyglobal
and
self
.
entry
.
is_member
:
if
self
.
entry
.
is_pyglobal
and
self
.
entry
.
is_member
:
env
.
use_utility_code
(
type_cache_invalidation_code
)
env
.
use_utility_code
(
type_cache_invalidation_code
)
def
analyse_types
(
self
,
env
):
def
analyse_types
(
self
,
env
,
entry
=
None
):
self
.
entry
=
env
.
lookup
(
self
.
name
)
if
entry
is
None
:
entry
=
env
.
lookup
(
self
.
name
)
self
.
entry
=
entry
if
not
self
.
entry
:
if
not
self
.
entry
:
self
.
entry
=
env
.
declare_builtin
(
self
.
name
,
self
.
pos
)
self
.
entry
=
env
.
declare_builtin
(
self
.
name
,
self
.
pos
)
if
not
self
.
entry
:
if
not
self
.
entry
:
...
...
Cython/Compiler/Nodes.py
View file @
90f19619
...
@@ -251,6 +251,11 @@ class StatListNode(Node):
...
@@ -251,6 +251,11 @@ class StatListNode(Node):
# stats a list of StatNode
# stats a list of StatNode
child_attrs
=
[
"stats"
]
child_attrs
=
[
"stats"
]
def
create_analysed
(
pos
,
env
,
*
args
,
**
kw
):
node
=
StatListNode
(
pos
,
*
args
,
**
kw
)
return
node
# No node-specific analysis necesarry
create_analysed
=
staticmethod
(
create_analysed
)
def
analyse_control_flow
(
self
,
env
):
def
analyse_control_flow
(
self
,
env
):
for
stat
in
self
.
stats
:
for
stat
in
self
.
stats
:
...
@@ -3522,6 +3527,12 @@ class TryFinallyStatNode(StatNode):
...
@@ -3522,6 +3527,12 @@ class TryFinallyStatNode(StatNode):
# There doesn't seem to be any point in disallowing
# There doesn't seem to be any point in disallowing
# continue in the try block, since we have no problem
# continue in the try block, since we have no problem
# handling it.
# handling it.
def
create_analysed
(
pos
,
env
,
body
,
finally_clause
):
node
=
TryFinallyStatNode
(
pos
,
body
=
body
,
finally_clause
=
finally_clause
)
node
.
cleanup_list
=
[]
return
node
create_analysed
=
staticmethod
(
create_analysed
)
def
analyse_control_flow
(
self
,
env
):
def
analyse_control_flow
(
self
,
env
):
env
.
start_branching
(
self
.
pos
)
env
.
start_branching
(
self
.
pos
)
...
...
tests/run/bufaccess.pyx
View file @
90f19619
cimport
__cython__
cimport
__cython__
__doc__
=
u"""
__doc__
=
u"""
>>> fb = MockBuffer("=f", "f", [1.0, 1.25, 0.75, 1.0], (2,2))
>>> A = MockBuffer("i", range(10), label="A")
>>> printbuf_float(fb, (2,2))
>>> B = MockBuffer("i", range(10), label="B")
1.0 1.25
>>> E = ErrorBuffer("E")
0.75 1.0
>>> acquire_release(A, B)
acquired A
released A
acquired B
released B
>>> acquire_raise(A)
acquired A
released A
Traceback (most recent call last):
...
Exception: on purpose
>>> printbuf_float(MockBuffer("f", [1.0, 1.25, 0.75, 1.0]), (4,))
acquired
1.0 1.25 0.75 1.0
released
>>> printbuf_int_2d(MockBuffer("i", range(6), (2,3)), (2,3))
acquired
0 1 2
3 4 5
released
"""
"""
def
acquire_release
(
o1
,
o2
):
cdef
object
[
int
]
buf
buf
=
o1
buf
=
o2
def
acquire_raise
(
o
):
cdef
object
[
int
]
buf
buf
=
o
raise
Exception
(
"on purpose"
)
def
printbuf_float
(
o
,
shape
):
def
printbuf_float
(
o
,
shape
):
# should make shape builtin
# should make shape builtin
cdef
object
[
float
,
2
]
buf
cdef
object
[
float
]
buf
buf
=
o
cdef
int
i
,
j
for
i
in
range
(
shape
[
0
]):
print
buf
[
i
],
print
def
printbuf_int_2d
(
o
,
shape
):
# should make shape builtin
cdef
object
[
int
,
2
]
buf
buf
=
o
buf
=
o
cdef
int
i
,
j
cdef
int
i
,
j
for
i
in
range
(
shape
[
0
]):
for
i
in
range
(
shape
[
0
]):
...
@@ -19,10 +57,21 @@ def printbuf_float(o, shape):
...
@@ -19,10 +57,21 @@ def printbuf_float(o, shape):
print
print
ctypedef
char
*
(
*
write_func_ptr
)(
char
*
,
object
)
cdef
char
*
write_float
(
char
*
buf
,
object
value
):
(
<
float
*>
buf
)[
0
]
=
<
float
>
value
return
buf
+
sizeof
(
float
)
cdef
char
*
write_int
(
char
*
buf
,
object
value
):
(
<
int
*>
buf
)[
0
]
=
<
int
>
value
return
buf
+
sizeof
(
int
)
sizes
=
{
# long can hold a pointer on all target platforms,
'f'
:
sizeof
(
float
)
# though really we should have a seperate typedef for this..
}
# TODO: Should create subclasses of MockBuffer instead.
typemap
=
{
'f'
:
(
sizeof
(
float
),
<
unsigned
long
>&
write_float
),
'i'
:
(
sizeof
(
int
),
<
unsigned
long
>&
write_int
)
}
cimport
stdlib
cimport
stdlib
...
@@ -32,14 +81,21 @@ cdef class MockBuffer:
...
@@ -32,14 +81,21 @@ cdef class MockBuffer:
cdef
int
len
,
itemsize
,
ndim
cdef
int
len
,
itemsize
,
ndim
cdef
Py_ssize_t
*
strides
cdef
Py_ssize_t
*
strides
cdef
Py_ssize_t
*
shape
cdef
Py_ssize_t
*
shape
cdef
write_func_ptr
wfunc
cdef
object
label
def
__init__
(
self
,
format
,
typechar
,
data
,
shape
=
None
,
strides
=
None
):
def
__init__
(
self
,
typechar
,
data
,
shape
=
None
,
strides
=
None
,
format
=
None
,
label
=
None
):
self
.
itemsize
=
sizes
[
typechar
]
self
.
label
=
label
if
format
is
None
:
format
=
"=%s"
%
typechar
self
.
itemsize
,
x
=
typemap
[
typechar
]
self
.
wfunc
=
<
write_func_ptr
><
unsigned
long
>
x
if
shape
is
None
:
shape
=
(
len
(
data
),)
if
shape
is
None
:
shape
=
(
len
(
data
),)
if
strides
is
None
:
if
strides
is
None
:
strides
=
[]
strides
=
[]
cumprod
=
1
cumprod
=
1
for
s
in
shape
:
rshape
=
list
(
shape
)
rshape
.
reverse
()
for
s
in
rshape
:
strides
.
append
(
cumprod
)
strides
.
append
(
cumprod
)
cumprod
*=
s
cumprod
*=
s
strides
.
reverse
()
strides
.
reverse
()
...
@@ -68,11 +124,32 @@ cdef class MockBuffer:
...
@@ -68,11 +124,32 @@ cdef class MockBuffer:
buffer
.
suboffsets
=
NULL
buffer
.
suboffsets
=
NULL
buffer
.
itemsize
=
self
.
itemsize
buffer
.
itemsize
=
self
.
itemsize
buffer
.
internal
=
NULL
buffer
.
internal
=
NULL
print
"acquired"
,
if
self
.
label
:
print
self
.
label
else
:
print
def
__releasebuffer__
(
MockBuffer
self
,
Py_buffer
*
buffer
):
print
"released"
,
if
self
.
label
:
print
self
.
label
else
:
print
cdef
fill_buffer
(
self
,
typechar
,
object
data
):
cdef
fill_buffer
(
self
,
typechar
,
object
data
):
cdef
int
idx
=
0
cdef
char
*
it
=
self
.
buffer
for
value
in
data
:
for
value
in
data
:
(
<
float
*>
(
self
.
buffer
+
idx
))[
0
]
=
<
float
>
value
it
=
self
.
wfunc
(
it
,
value
)
idx
+=
sizeof
(
float
)
cdef
class
ErrorBuffer
:
cdef
object
label
def
__init__
(
self
,
label
):
self
.
label
=
label
def
__getbuffer__
(
MockBuffer
self
,
Py_buffer
*
buffer
,
int
flags
):
raise
Exception
(
"acquiring %s"
%
self
.
label
)
def
__releasebuffer__
(
MockBuffer
self
,
Py_buffer
*
buffer
):
raise
Exception
(
"releasing %s"
%
self
.
label
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment