...
 
Commits (65)
......@@ -4,7 +4,7 @@
from __future__ import absolute_import
from .Symtab import BuiltinScope, StructOrUnionScope, Scope
from .Symtab import BuiltinScope, StructOrUnionScope, CppClassScope
from .Code import UtilityCode
from .TypeSlots import Signature
from . import PyrexTypes
......@@ -387,7 +387,7 @@ def inject_cy_object(self):
scope.inherited_var_entries = []
scope.inherited_type_entries = []
cy_object_scope = Scope("CyObject", self, None)
cy_object_scope = CppClassScope("CyObject", self, None)
init_scope(cy_object_scope)
cy_object_type = PyrexTypes.cy_object_type
cy_object_scope.type = PyrexTypes.cy_object_type
......@@ -411,11 +411,11 @@ def inject_acthon_interfaces(self):
# int getIntResult(){}
# operator int() { return this->getIntResult(); }
result_scope = Scope("ActhonResultInterface", self, None)
result_scope = CppClassScope("ActhonResultInterface", self, None)
init_scope(result_scope)
acthon_result_type = result_type = PyrexTypes.CypClassType(
"ActhonResultInterface", result_scope, "ActhonResultInterface", (PyrexTypes.cy_object_type,),
lock_mode="autolock", activable=False)
activable=False)
result_scope.type = result_type
#result_type.set_scope is required because parent_type is used when doing scope inheritance
result_type.set_scope(result_scope)
......@@ -470,11 +470,11 @@ def inject_acthon_interfaces(self):
# cypclass ActhonMessageInterface
message_scope = Scope("ActhonMessageInterface", self, None)
message_scope = CppClassScope("ActhonMessageInterface", self, None)
init_scope(message_scope)
acthon_message_type = message_type = PyrexTypes.CypClassType(
"ActhonMessageInterface", message_scope, "ActhonMessageInterface", (PyrexTypes.cy_object_type,),
lock_mode="autolock", activable=False)
activable=False)
message_type.set_scope(message_scope)
message_scope.type = message_type
......@@ -484,11 +484,11 @@ def inject_acthon_interfaces(self):
# void insertActivity(ActhonMessageInterface msg){}
# void removeActivity(ActhonMessageInterface msg){}
sync_scope = Scope("ActhonSyncInterface", self, None)
sync_scope = CppClassScope("ActhonSyncInterface", self, None)
init_scope(sync_scope)
acthon_sync_type = sync_type = PyrexTypes.CypClassType(
"ActhonSyncInterface", sync_scope, "ActhonSyncInterface", (PyrexTypes.cy_object_type,),
lock_mode="autolock", activable=False)
activable=False)
sync_type.set_scope(sync_scope)
sync_scope.type = sync_type
sync_entry = self.declare("ActhonSyncInterface", "ActhonSyncInterface", sync_type, None, "extern")
......@@ -510,9 +510,8 @@ def inject_acthon_interfaces(self):
sync_isCompleted_entry.is_variable = 1
sync_scope.var_entries.append(sync_isCompleted_entry)
sync_msg_arg = PyrexTypes.CFuncTypeArg("msg", message_type, None)
sync_insertActivity_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [sync_msg_arg], nogil = 1)
sync_removeActivity_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [sync_msg_arg], nogil = 1)
sync_insertActivity_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [], nogil = 1)
sync_removeActivity_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [], nogil = 1)
sync_insertActivity_entry = sync_scope.declare("insertActivity", "insertActivity",
sync_insertActivity_type, None, "extern")
sync_insertActivity_entry.is_cfunction = 1
......@@ -533,12 +532,12 @@ def inject_acthon_interfaces(self):
message_entry.is_type = 1
message_sync_attr_entry = message_scope.declare("_sync_method", "_sync_method",
sync_type, None, "extern")
PyrexTypes.cyp_class_qualified_type(sync_type, 'lock'), None, "extern")
message_sync_attr_entry.is_variable = 1
message_scope.var_entries.append(message_sync_attr_entry)
message_result_attr_entry = message_scope.declare("_result", "_result",
result_type, None, "extern")
PyrexTypes.cyp_class_qualified_type(result_type, 'lock'), None, "extern")
message_result_attr_entry.is_variable = 1
message_scope.var_entries.append(message_result_attr_entry)
......@@ -553,18 +552,18 @@ def inject_acthon_interfaces(self):
# void push(ActhonMessageInterface message){}
# bool activate(){}
queue_scope = Scope("ActhonQueueInterface", self, None)
queue_scope = CppClassScope("ActhonQueueInterface", self, None)
init_scope(queue_scope)
acthon_queue_type = queue_type = PyrexTypes.CypClassType(
"ActhonQueueInterface", queue_scope, "ActhonQueueInterface", (PyrexTypes.cy_object_type,),
lock_mode="autolock", activable=False)
activable=False)
queue_type.set_scope(queue_scope)
queue_scope.type = queue_type
queue_entry = self.declare("ActhonQueueInterface", "ActhonQueueInterface", queue_type, self, "extern")
queue_entry.is_type = 1
queue_msg_arg = PyrexTypes.CFuncTypeArg("msg", message_type, None)
queue_push_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [queue_msg_arg], nogil = 1)
queue_push_type = PyrexTypes.CFuncType(PyrexTypes.c_void_type, [queue_msg_arg], nogil = 1, self_qualifier = 'locked')
queue_push_entry = queue_scope.declare("push", "push", queue_push_type,
None, "extern")
queue_push_entry.is_cfunction = 1
......@@ -590,11 +589,11 @@ def inject_acthon_interfaces(self):
# ResultInterface (*_active_result_class)()
# QueueInterface _active_queue_class
activable_scope = Scope("ActhonActivableClass", self, None)
activable_scope = CppClassScope("ActhonActivableClass", self, None)
init_scope(activable_scope)
acthon_activable_type = activable_type = PyrexTypes.CypClassType(
"ActhonActivableClass", activable_scope, "ActhonActivableClass", (PyrexTypes.cy_object_type,),
lock_mode="autolock", activable=False)
activable=False)
activable_type.set_scope(activable_scope)
activable_entry = self.declare("ActhonActivableClass", None, activable_type, "ActhonActivableClass", "extern")
activable_entry.is_type = 1
......@@ -606,7 +605,7 @@ def inject_acthon_interfaces(self):
activable_scope.var_entries.append(activable_result_attr_entry)
activable_queue_attr_entry = activable_scope.declare("_active_queue_class", "_active_queue_class",
queue_type, None, "extern")
PyrexTypes.cyp_class_qualified_type(queue_type, 'lock'), None, "extern")
activable_queue_attr_entry.is_variable = 1
activable_scope.var_entries.append(activable_queue_attr_entry)
......
......@@ -849,7 +849,7 @@ class FunctionState(object):
elif type.is_cfunction:
from . import PyrexTypes
type = PyrexTypes.c_ptr_type(type) # A function itself isn't an l-value
if not type.is_pyobject and not type.is_memoryviewslice and not type.is_cyp_class:
if not type.is_pyobject and not type.is_memoryviewslice:
# Make manage_ref canonical, so that manage_ref will always mean
# a decref is needed.
manage_ref = False
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -170,6 +170,11 @@ api_name = pyrex_prefix + "capi__"
# cname for the type that defines the essential memory layout of a cypclass wrapper.
cypclass_wrapper_layout_type = "CyPyObject"
# active cypclass
cypclass_reified_prefix = builtin_prefix + 'active_'
cypclass_active_func_prefix = func_prefix + 'active_'
cypclass_active_self_cname = "_active_self"
# the h and api guards get changed to:
# __PYX_HAVE__FILENAME (for ascii filenames)
# __PYX_HAVE_U_PUNYCODEFILENAME (for non-ascii filenames)
......
This diff is collapsed.
......@@ -309,6 +309,8 @@ def _p_factor(s):
return p_typecast(s)
elif sy == 'IDENT' and s.systring == "sizeof":
return p_sizeof(s)
elif sy == 'IDENT' and s.systring == "consume":
return p_consume(s)
return p_power(s)
def p_typecast(s):
......@@ -319,7 +321,8 @@ def p_typecast(s):
is_memslice = isinstance(base_type, Nodes.MemoryViewSliceTypeNode)
is_template = isinstance(base_type, Nodes.TemplatedTypeNode)
is_const_volatile = isinstance(base_type, Nodes.CConstOrVolatileTypeNode)
if not is_memslice and not is_template and not is_const_volatile and base_type.name is None:
is_qualified = isinstance(base_type, Nodes.QualifiedCypclassNode)
if not is_memslice and not is_template and not is_const_volatile and not is_qualified and base_type.name is None:
s.error("Unknown type")
declarator = p_c_declarator(s, empty = 1)
if s.sy == '?':
......@@ -357,6 +360,13 @@ def p_sizeof(s):
s.expect(')')
return node
def p_consume(s):
# s.sy == ident "consume"
pos = s.position()
s.next()
operand = p_factor(s)
return ExprNodes.ConsumeNode(pos, operand = operand)
def p_yield_expression(s):
# s.sy == "yield"
......@@ -2534,6 +2544,13 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
return Nodes.CConstOrVolatileTypeNode(pos,
base_type=base_type, is_const=is_const, is_volatile=is_volatile)
# Handle cypclass qualifiers
if s.sy == 'IDENT' and s.systring in ('active', 'iso', 'lock', 'locked'):
qualifier = s.systring
s.next()
base_type = p_c_base_type(s, self_flag=self_flag, nonempty=nonempty, templates=templates)
return Nodes.QualifiedCypclassNode(pos, base_type=base_type, qualifier=qualifier)
if s.sy != 'IDENT':
error(pos, "Expected an identifier, found '%s'" % s.sy)
if looking_at_base_type(s):
......@@ -3848,10 +3865,8 @@ def p_cpp_class_definition(s, pos, ctx):
if s.sy == '[':
error(s.position(), "Name options not allowed for C++ class")
nogil = p_nogil(s) or cypclass
lock_mode = None
activable = False
if cypclass:
lock_mode = p_cypclass_lock_mode(s)
activable = p_cypclass_activable(s)
if s.sy == ':':
s.next()
......@@ -3881,7 +3896,7 @@ def p_cpp_class_definition(s, pos, ctx):
visibility = ctx.visibility,
in_pxd = ctx.level == 'module_pxd',
attributes = attributes,
templates = templates, cypclass=cypclass, lock_mode=lock_mode, activable=activable)
templates = templates, cypclass=cypclass, activable=activable)
def p_cpp_class_attribute(s, ctx):
decorators = None
......@@ -3907,14 +3922,6 @@ def p_cpp_class_attribute(s, ctx):
node.decorators = decorators
return node
def p_cypclass_lock_mode(s):
if s.sy == 'IDENT' and s.systring in ('nolock', 'checklock', 'autolock'):
mode = s.systring
s.next()
return mode
else:
return None
def p_cypclass_activable(s):
if s.sy == 'IDENT' and s.systring == 'activable':
s.next()
......
This diff is collapsed.
This diff is collapsed.
......@@ -538,6 +538,8 @@ def simply_type(result_type, pos):
result_type = result_type.ref_base_type
if result_type.is_cv_qualified:
result_type = result_type.cv_base_type
if result_type.is_qualified_cyp_class and result_type.qualifier == 'iso~':
result_type = PyrexTypes.cyp_class_qualified_type(result_type.qual_base_type, 'iso')
if result_type.is_cpp_class:
result_type.check_nullary_constructor(pos)
if result_type.is_array:
......
This diff is collapsed.
# tag: cpp
# mode: compile
cdef cypclass A[T] activable:
int foo(self):
return 0
void bar(self):
pass
# tag: cpp
# mode: compile
cdef cypclass B:
pass
cdef cypclass A[T]:
T t
B b
# mode: error
# tag: cpp, cpp11, pthread
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass A activable:
void f(self, A other):
pass
void f_iso(self, iso A other):
pass
void f_lock(self, lock A other):
pass
void f_active(self, active A other):
pass
def test_aliasing():
cdef active A active_a
# Aliasing from active
cdef iso A iso_a
iso_a = active_a
cdef lock A lock_a
lock_a = active_a
cdef A ref_a
ref_a = active_a
# Aliasing to active
cdef active A active_b
active_b = A()
cdef active A active_c
active_c = consume A()
cdef active A active_d
active_d = <lock A> consume A()
def test_calling():
a = activate(consume A())
a.f(NULL, A())
a.f(NULL, consume A())
cdef iso A iso_a
a.f_iso(NULL, consume iso_a)
cdef lock A lock_a
a.f_lock(NULL, lock_a)
cdef active A active_a
a.f_active(NULL, active_a)
def test_typecast():
cdef active A active_a
# Casting from active
cdef iso A iso_a
iso_a = consume <iso A> active_a
cdef lock A lock_a
lock_a = <lock A> active_a
cdef A ref_a
ref_a = <A> active_a
# Casting to active
cdef active A active_b
active_b = <active A> A()
cdef active A active_c
active_c = <active A> <iso A> consume A()
cdef active A active_d
active_d = <active A> <lock A> consume A()
_ERRORS = u'''
24:12: Cannot assign type 'active A' to 'iso A'
27:13: Cannot assign type 'active A' to 'lock A'
30:12: Cannot assign type 'active A' to 'A'
34:16: Cannot assign type 'A' to 'active A'
40:15: Cannot assign type 'lock A' to 'active A'
46:15: Cannot assign type 'A' to 'iso-> A'
65:20: Cannot cast 'active A' to 'iso A'
68:13: Cannot cast 'active A' to 'lock A'
71:12: Cannot cast 'active A' to 'A'
75:15: Cannot cast 'A' to 'active A'
78:15: Cannot cast 'iso A' to 'active A'
81:15: Cannot cast 'lock A' to 'active A'
'''
# mode: error
# tag: cpp, cpp11, pthread
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass A activable:
pass
def test_name_aliasing():
cdef iso A iso_a
iso_a = consume A()
# Aliasing to iso
cdef iso A iso_b
iso_b = iso_a
cdef iso A iso_c
iso_c = A()
cdef iso A iso_d
iso_d = activate(consume A())
cdef iso A iso_e
iso_e = <object> A()
# Aliasing iso
cdef iso A iso_f
iso_f = iso_a
cdef active A active_a
active_a = iso_a
cdef A ref_a
ref_a = iso_a
cdef object py_a
py_a = iso_a
cdef cypclass Field:
Field foo(self, Field other):
return other
cdef cypclass Origin:
Field field
__init__(self):
self.field = Field()
Field bar(self, Field other):
return other
def test_field_aliasing():
cdef iso Origin o = consume Origin()
cdef object py_field
# OK - can pass consumed arguments
o.bar(consume Field()).foo(consume Field())
# ERR - aliasing field of iso to pyobject
py_field = o.field
# ERR - pyobject to field of iso
o.field = py_field
# ERR - aliasing field of iso
field = o.field
# ERR - consuming field of iso
field2 = consume o.field
# ERR - non_consumed argument
o.bar(Field())
# ERR - aliasing the returned reference
c = o.bar(consume Field())
def test_typecast():
cdef iso A iso_a
iso_a = consume A()
# Casting to iso
cdef iso A iso_b
iso_b = <iso A> A()
cdef iso A iso_c
iso_c = <iso A> activate(consume A())
cdef iso A iso_d
iso_d = <iso A> <object> A()
# Casting from iso
cdef active A active_a
active_a = <active A> iso_a
cdef A ref_a
ref_a = <A> iso_a
cdef object py_a
py_a = <object> iso_a
cdef iso A iso_e
iso_e = <iso A> iso_a
cdef iso A iso_f
iso_f = consume <iso A> iso_a
_ERRORS = u'''
14:12: Cannot assign type 'iso A' to 'iso A'
17:13: Cannot assign type 'A' to 'iso A'
20:20: Cannot assign type 'active A' to 'iso A'
23:12: Cannot convert Python object to 'iso A'
27:12: Cannot assign type 'iso A' to 'iso A'
30:15: Cannot assign type 'iso A' to 'active A'
33:12: Cannot assign type 'iso A' to 'A'
36:11: Cannot convert 'iso A' to Python object
60:16: Cannot convert 'iso-> Field' to Python object
63:14: Cannot convert Python object to 'iso-> Field'
66:13: Cannot assign type 'iso-> Field' to 'iso-> Field'
72:15: Cannot assign type 'Field' to 'iso-> Field'
75:13: Cannot assign type 'iso-> Field' to 'iso-> Field'
84:12: Cannot assign type 'iso A' to 'iso A'
84:12: Cannot cast 'A' to 'iso A'
87:12: Cannot assign type 'iso A' to 'iso A'
87:12: Cannot cast 'active A' to 'iso A'
90:12: Cannot assign type 'iso A' to 'iso A'
94:15: Cannot cast 'iso A' to 'active A'
97:12: Cannot cast 'iso A' to 'A'
100:11: Cannot cast 'iso A' to 'Python object'
103:12: Cannot assign type 'iso A' to 'iso A'
'''
# mode: error
# tag: cpp, cpp11, pthread
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass A checklock:
int a
int getter(const self):
return self.a
void setter(self, int a):
self.a = a
cdef void take_write_locked(A obj):
pass
cdef int take_read_locked(const A obj):
return 3
def incorrect_locks():
obj = A()
obj.a = 3
obj.getter()
with rlocked obj:
obj.setter(42)
take_write_locked(obj)
obj.a
take_read_locked(obj)
cdef A global_cyobject
cdef void global_lock_taking():
with wlocked global_cyobject:
global_cyobject.setter(global_cyobject.getter() + 1)
_ERRORS = u"""
20:4: Reference 'obj' is not correctly locked in this expression (write lock required)
21:4: Reference 'obj' is not correctly locked in this expression (read lock required)
23:8: Reference 'obj' is not correctly locked in this expression (write lock required)
24:26: Reference 'obj' is not correctly locked in this expression (write lock required)
25:4: Reference 'obj' is not correctly locked in this expression (read lock required)
26:21: Reference 'obj' is not correctly locked in this expression (read lock required)
32:17: Can only lock local variables or arguments
"""
# mode: error
# tag: cpp, cpp11, pthread
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass A activable:
void f(self, A other):
pass
void f_iso(self, iso A other):
pass
void f_lock(self, lock A other):
pass
void f_active(self, active A other):
pass
void f_locked_self(locked self):
cdef lock A l = self
def test_aliasing():
cdef lock A lock_a
# Aliasing from lock
cdef iso A iso_a
iso_a = lock_a
cdef active A active_a
active_a = lock_a
cdef locked A locked_a
locked_a = lock_a
cdef A ref_a
ref_a = lock_a
# Aliasing to lock
cdef lock A lock_b
lock_b = A()
cdef lock A lock_c
lock_c = consume A()
cdef lock A lock_d
lock_d = <lock A> consume A()
cdef lock A lock_e
cdef locked A locked_b
lock_e = locked_b
def test_calling():
cdef lock A a
a.f(A())
a.f(consume A())
a.f_locked_self()
cdef iso A iso_a
a.f_iso(consume iso_a)
cdef lock A lock_a
a.f_lock(lock_a)
cdef active A active_a
a.f_active(active_a)
def test_typecast():
cdef lock A lock_a
# Casting from lock
cdef iso A iso_a
iso_a = consume <iso A> lock_a
cdef active A active_a
active_a = <active A> lock_a
cdef locked A locked_a
locked_a = <locked A> lock_a
cdef A ref_a
ref_a = <A> lock_a
# Casting to lock
cdef lock A lock_b
lock_b = <lock A> A()
cdef lock A lock_c
lock_c = <lock A> <iso A> consume A()
cdef lock A lock_d
lock_d = <lock A> activate(consume A())
cdef lock A lock_e
cdef locked A locked_b
lock_e = <lock A> locked_b
_ERRORS = u'''
27:12: Cannot assign type 'lock A' to 'iso A'
30:15: Cannot assign type 'lock A' to 'active A'
33:15: Cannot assign type 'lock A' to 'locked A'
36:12: Cannot assign type 'lock A' to 'A'
40:14: Cannot assign type 'A' to 'lock A'
56:9: Cannot assign type 'A' to 'lock-> A'
77:20: Cannot cast 'lock A' to 'iso A'
80:15: Cannot cast 'lock A' to 'active A'
83:15: Cannot cast 'lock A' to 'locked A'
86:12: Cannot cast 'lock A' to 'A'
90:13: Cannot cast 'A' to 'lock A'
93:13: Cannot cast 'iso A' to 'lock A'
96:13: Cannot cast 'active A' to 'lock A'
'''
# mode: error
# tag: cpp, cpp11, pthread
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass Error:
locked Error prohibited_field_type
locked Error forward_prohibited_return_type(self)
locked Error prohibited_return_type(self):
pass
cdef locked Error prohibited_global_variable
cdef cypclass A:
void f(locked self):
pass
void g(self, locked A other):
pass
void h(self, A other):
cdef locked A a
def test_aliasing():
cdef locked A locked_a
cdef lock A lock_a
lock_a = locked_a
locked_a = lock_a
lock_a.f()
A().g(locked_a)
A().g(lock_a)
_ERRORS = u'''
6:4: 'locked' variables are only allowed inside a function
8:47: Function cannot return a 'locked' cypclass instance
10:39: Function cannot return a 'locked' cypclass instance
13:5: 'locked' variables are only allowed inside a function
33:15: Cannot assign type 'lock A' to 'locked A'
39:10: Cannot assign type 'lock A' to 'locked A'
'''
......@@ -14,7 +14,7 @@ cdef extern from "<semaphore.h>" nogil:
int sem_destroy(sem_t* sem)
cdef cypclass BasicQueue(ActhonQueueInterface) checklock:
cdef cypclass BasicQueue(ActhonQueueInterface):
message_queue_t* _queue
__init__(self):
......@@ -26,10 +26,10 @@ cdef cypclass BasicQueue(ActhonQueueInterface) checklock:
bint is_empty(const self):
return self._queue.empty()
void push(self, ActhonMessageInterface message):
void push(locked self, ActhonMessageInterface message):
self._queue.push_back(message)
if message._sync_method is not NULL:
message._sync_method.insertActivity(message)
message._sync_method.insertActivity()
bint activate(self):
cdef bint one_message_processed
......@@ -47,13 +47,13 @@ cdef cypclass BasicQueue(ActhonQueueInterface) checklock:
if next_message._sync_method is not NULL:
next_sync_method = next_message._sync_method
with wlocked next_sync_method:
next_sync_method.removeActivity(next_message)
next_sync_method.removeActivity()
else:
self._queue.push_back(next_message)
# Don't forget to incref to avoid premature deallocation
return one_message_processed
cdef cypclass NoneResult(ActhonResultInterface) checklock:
cdef cypclass NoneResult(ActhonResultInterface):
void pushVoidStarResult(self, void* result):
pass
void pushIntResult(self, int result):
......@@ -63,7 +63,7 @@ cdef cypclass NoneResult(ActhonResultInterface) checklock:
int getIntResult(const self):
return 0
cdef cypclass WaitResult(ActhonResultInterface) checklock:
cdef cypclass WaitResult(ActhonResultInterface):
union result_t:
int int_val
void* ptr
......@@ -104,18 +104,18 @@ cdef cypclass WaitResult(ActhonResultInterface) checklock:
res = self._getRawResult()
return res.int_val
cdef cypclass ActivityCounterSync(ActhonSyncInterface) checklock:
cdef cypclass ActivityCounterSync(ActhonSyncInterface):
int count
ActivityCounterSync previous_sync
lock ActivityCounterSync previous_sync
__init__(self, ActivityCounterSync prev = <ActivityCounterSync> NULL):
__init__(self, lock ActivityCounterSync prev = NULL):
self.count = 0
self.previous_sync = prev
void insertActivity(self, ActhonMessageInterface msg):
void insertActivity(self):
self.count += 1
void removeActivity(self, ActhonMessageInterface msg):
void removeActivity(self):
self.count -= 1
bint isCompleted(const self):
......@@ -129,12 +129,12 @@ cdef cypclass ActivityCounterSync(ActhonSyncInterface) checklock:
res = prev_sync.isCompleted()
return res
cdef cypclass A checklock activable:
cdef cypclass A activable:
int a
__init__(self):
self.a = 0
self._active_result_class = WaitResult.construct
self._active_queue_class = BasicQueue()
self._active_queue_class = consume BasicQueue()
int getter(const self):
return self.a
void setter(self, int a):
......@@ -146,21 +146,19 @@ def test_acthon_chain(n):
42
"""
cdef ActhonResultInterface res
cdef ActhonQueueInterface queue
sync1 = ActivityCounterSync()
with wlocked sync1:
after_sync1 = ActivityCounterSync(sync1)
cdef lock ActhonQueueInterface queue
sync1 = <lock ActivityCounterSync> consume ActivityCounterSync()
after_sync1 = <lock ActivityCounterSync> consume ActivityCounterSync(sync1)
obj = A()
with wlocked obj:
obj_actor = obj.__activate__()
with wlocked obj_actor, wlocked sync1, wlocked after_sync1:
# Pushing things in the queue
obj_actor.setter(sync1, n)
res = obj_actor.getter(after_sync1)
queue = obj._active_queue_class
obj_actor = activate(consume obj)
# Pushing things in the queue
obj_actor.setter(sync1, n)
res = obj_actor.getter(after_sync1)
# Processing the queue
with rlocked obj:
queue = obj._active_queue_class
with wlocked queue:
while not queue.is_empty():
queue.activate()
while not queue.is_empty():
queue.activate()
print <int> res
This diff is collapsed.
# mode: run
# tag: cpp, cpp11, pthread
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass Refcounted:
__dealloc__(self) with gil:
print("Refcounted destroyed")
def test_consume_name():
"""
>>> test_consume_name()
Refcounted destroyed
0
"""
r0 = Refcounted()
if Cy_GETREF(r0) != 2:
return -1
cdef Refcounted r1 = consume r0
if r0 is not NULL:
return -2
if Cy_GETREF(r1) != 2:
return -3
return 0
def test_consume_iso_name():
"""
>>> test_consume_iso_name()
Refcounted destroyed
0
"""
cdef iso Refcounted r0 = consume Refcounted()
cdef Refcounted r1 = consume r0
if r0 is not NULL:
return -2
if Cy_GETREF(r1) != 2:
return -3
return 0
def test_consume_and_drop_name():
"""
>>> test_consume_and_drop_name()
Refcounted destroyed
consumed
0
"""
r = Refcounted()
if Cy_GETREF(r) != 2:
return -1
consume r
print("consumed")
if r is not NULL:
return -2
return 0
def test_consume_constructed():
"""
>>> test_consume_constructed()
Refcounted destroyed
0
"""
cdef Refcounted r = consume Refcounted()
if Cy_GETREF(r) != 2:
return -1
return 0
def test_consume_iso_constructed():
"""
>>> test_consume_iso_constructed()
Refcounted destroyed
0
"""
cdef Refcounted r = consume new Refcounted()
if Cy_GETREF(r) != 2:
return -1
return 0
def test_consume_and_drop_constructed():
"""
>>> test_consume_and_drop_constructed()
Refcounted destroyed
consumed
0
"""
consume Refcounted()
print("consumed")
return 0
cdef cypclass Origin:
Refcounted field
__init__(self):
self.field = Refcounted()
cdef cypclass OriginIso:
iso Refcounted field
__init__(self):
self.field = consume Refcounted()
def test_consume_field():
"""
>>> test_consume_field()
Refcounted destroyed
0
"""
cdef Refcounted r = consume Origin().field
if Cy_GETREF(r) != 2:
return -1
return 0
def test_consume_iso_field():
"""
>>> test_consume_iso_field()
Refcounted destroyed
0
"""
cdef Refcounted r = consume OriginIso().field
if Cy_GETREF(r) != 2:
return -1
return 0
def test_consume_and_drop_field():
"""
>>> test_consume_and_drop_field()
Refcounted destroyed
consumed
0
"""
consume Origin().field
print("consumed")
return 0
def test_consume_cast_name():
"""
>>> test_consume_cast_name()
Refcounted destroyed
0
"""
r0 = Refcounted()
if Cy_GETREF(r0) != 2:
return -1
cdef Refcounted r1 = consume <Refcounted> r0
if r0 is not NULL:
return -2
if Cy_GETREF(r1) != 2:
return -3
return 0
def test_consume_cast_constructed():
"""
>>> test_consume_cast_constructed()
Refcounted destroyed
0
"""
cdef Refcounted r = consume <Refcounted> Refcounted()
if Cy_GETREF(r) != 2:
return -1
return 0
def test_consume_cast_field():
"""
>>> test_consume_cast_field()
Refcounted destroyed
0
"""
cdef Refcounted r = consume <Refcounted> Origin().field
if Cy_GETREF(r) != 2:
return -1
return 0
cdef cypclass Convertible:
Refcounted __Refcounted__(self):
return Refcounted()
__dealloc__(self) with gil:
print("Convertible destroyed")
def test_consume_converted_name():
"""
>>> test_consume_converted_name()
Convertible destroyed
Refcounted destroyed
0
"""
c = Convertible()
if Cy_GETREF(c) != 2:
return -1
cdef Refcounted r = consume <Refcounted> c
if c is NULL:
return -2
if Cy_GETREF(c) != 2:
return -3
if Cy_GETREF(r) != 2:
return -4
del c
return 0
def test_consume_converted_constructed():
"""
>>> test_consume_converted_constructed()
Convertible destroyed
Refcounted destroyed
0
"""
cdef Refcounted r = consume <Refcounted> Convertible()
if Cy_GETREF(r) != 2:
return -1
return 0
cdef cypclass OriginConvertible:
Convertible field
__init__(self):
self.field = Convertible()
def test_consume_converted_field():
"""
>>> test_consume_converted_field()
Convertible destroyed
Refcounted destroyed
0
"""
o = OriginConvertible()
if Cy_GETREF(o.field) != 2:
return -1
cdef Refcounted r = consume <Refcounted> o.field
if o.field is NULL:
return -2
if Cy_GETREF(o.field) != 2:
return -3
if Cy_GETREF(r) != 2:
return -4
return 0
......@@ -2,7 +2,7 @@
# tag: cpp, cpp11
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass Refcounted nolock:
cdef cypclass Refcounted:
pass
cdef int raises(Refcounted r) except 0:
......
......@@ -2,18 +2,18 @@
# tag: cpp, cpp11
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass A nolock:
cdef cypclass A:
int val
__init__(self, int a):
self.val = a
A __iadd__(self, A other):
self.val += (other.val + 1)
cdef cypclass B(A) nolock:
cdef cypclass B(A):
B __iadd__(self, A other):
self.val += (other.val + 10)
int is_inferred_as_B(self):
return 1
......@@ -30,7 +30,7 @@ def test_inplace_operator_inference():
a += b # should add 1
# before it being fixed, 'b += a' where 'a' is of type A caused 'b' to be inferred as type A instead of B.
b += a # should add 10
# since all cypclass methods are virtual, 'b' being erroneously inferred as type A would cause a compilation error
......
# mode: run
# tag: cpp, cpp11, pthread
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass A checklock:
int a
__init__(self):
self.a = 0
int getter(const self):
return self.a
void setter(self, int a):
self.a = a
def test_basic_locking():
"""
>>> test_basic_locking()
0
"""
obj = A()
with rlocked obj:
print obj.getter()
cdef argument_recursivity(A obj, int arg):
if arg > 0:
obj.setter(obj.getter() + 1)
argument_recursivity(obj, arg - 1)
def test_argument_recursivity(n):
"""
>>> test_argument_recursivity(42)
42
"""
obj = A()
with wlocked obj:
argument_recursivity(obj, n)
print obj.a
cdef cypclass Container:
A object
__init__(self):
self.object = A()
def test_lock_traversal(n):
"""
>>> test_lock_traversal(42)
42
"""
container = Container()
with rlocked container:
contained = container.object
with wlocked contained:
argument_recursivity(contained, n)
print contained.getter()
......@@ -2,10 +2,10 @@
# tag: cpp, cpp11
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass A nolock:
cdef cypclass A:
int a
cypclass B nolock:
cypclass B:
int b
__init__(self, int b):
self.b = b
......@@ -18,7 +18,7 @@ cdef cypclass A nolock:
__init__(self, int a, int b):
self.a = a
self.b = B(b)
int foo(self):
return self.a + self.b.foo()
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.