...
 
Commits (69)
......@@ -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,10 @@ 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 == "recover":
return p_recover(s)
elif sy == 'IDENT' and s.systring == "consume":
return p_consume(s)
return p_power(s)
def p_typecast(s):
......@@ -319,7 +323,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 +362,20 @@ def p_sizeof(s):
s.expect(')')
return node
def p_recover(s):
# s.sy == ident "recover"
pos = s.position()
s.next()
operand = p_factor(s)
return ExprNodes.RecoverNode(pos, operand = operand)
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 +2553,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 +3874,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 +3905,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 +3931,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 = recover A()
cdef active A active_d
active_d = <lock A> recover A()
def test_calling():
a = activate(recover A())
a.f(NULL, A())
a.f(NULL, recover A())
cdef iso A iso_a
a.f_iso(NULL, recover 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 = recover <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> recover A()
cdef active A active_d
active_d = <active A> <lock A> recover 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:
pass
def test_consume_iso_to_iso():
cdef iso A a = recover A()
cdef iso A b = consume a
def test_consume_mut_to_iso():
cdef A a = A()
cdef iso A b = consume a
def consume_rvalue():
a = consume A()
_ERRORS = u'''
14:19: Cannot assign type 'A' to 'iso A'
17:8: Can only consume named variables or fields
'''
# 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 = recover 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(recover 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 = recover Origin()
cdef object py_field
# OK - can pass recovered arguments
o.bar(recover Field()).foo(recover 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 = recover o.field
# ERR - non_recovered argument
o.bar(Field())
# ERR - aliasing the returned reference
c = o.bar(recover Field())
def test_typecast():
cdef iso A iso_a
iso_a = recover A()
# Casting to iso
cdef iso A iso_b
iso_b = <iso A> A()
cdef iso A iso_c
iso_c = <iso A> activate(recover 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 = recover <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 = recover A()
cdef lock A lock_d
lock_d = <lock A> recover 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(recover A())
a.f_locked_self()
cdef iso A iso_a
a.f_iso(recover 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 = recover <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> recover A()
cdef lock A lock_d
lock_d = <lock A> activate(recover 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 = recover 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> recover ActivityCounterSync()
after_sync1 = <lock ActivityCounterSync> recover 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(recover 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
# mode: run
# tag: cpp, cpp11, pthread
# cython: experimental_cpp_class_def=True, language_level=2
cdef cypclass A:
pass
def test_consume():
"""
>>> test_consume()
0
"""
a = A()
old_a = a
b = consume a
if a is not NULL:
return -1
if b is not old_a:
return -2
return 0
cdef cypclass Origin:
A field
__init__(self):
self.field = A()
def test_consume_field():
o = Origin()
old_field = o.field
a = consume o.field
if o.field is not NULL:
return -1
if a is not old_field:
return -2
return 0
# 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 = recover 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
cdef cypclass Origin:
Refcounted field
__init__(self):
self.field = Refcounted()
cdef cypclass OriginIso:
iso Refcounted field
__init__(self):
self.field = recover Refcounted()
def test_consume_field():
"""
>>> test_consume_field()
Refcounted destroyed
0
"""
cdef Origin o = Origin()
cdef Refcounted r = consume o.field
if Cy_GETREF(r) != 2:
return -1
if o.field is not NULL:
return -2
return 0
def test_consume_and_drop_field():
"""
>>> test_consume_and_drop_field()
Refcounted destroyed
consumed
0
"""
cdef Origin o = Origin()
consume o.field
print("consumed")
if o.field is not NULL:
return -2
return 0
def test_consume_iso_field():
"""
>>> test_consume_iso_field()
consumed
Refcounted destroyed
0
"""
cdef OriginIso o = OriginIso()
cdef iso Refcounted r = consume o.field
print("consumed")
if o.field is not NULL:
return -1
return 0
def test_consume_and_drop_iso_field():
"""
>>> test_consume_and_drop_iso_field()
Refcounted destroyed
consumed
0
"""
cdef OriginIso o = OriginIso()
consume o.field
print("consumed")
if o.field is not NULL:
return -1
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()
......
# mode: run
# tag: cpp, cpp11
# cython: experimental_cpp_class_def=True, language_level=2
from libc.stdio cimport printf
cdef cypclass Value:
__dealloc__(self) with gil:
print("Value destroyed")
cdef cypclass Arg:
__dealloc__(self) with gil:
print("Arg destroyed")
cdef cypclass Binop:
Value __add__(self, Arg a):
return Value()
def test_binop():
"""
>>> test_binop()
Arg destroyed
Value destroyed
"""
cdef Value r0
with nogil:
bin = Binop()
r0 = bin + Arg()
cdef cypclass Cmp:
Value __eq__(self, Arg a):
return Value()
def test_cmp():
"""
>>> test_cmp()
Arg destroyed
Value destroyed
"""
cdef Value r0
with nogil:
cmp = Cmp()
r0 = cmp == Arg()
return
cdef cypclass InplaceOps:
Value val
InplaceOps __iadd__(self, Arg a):
self.val = Value()
def test_inplace_ops():
"""
>>> test_inplace_ops()
Arg destroyed
Value destroyed
"""
cdef Value r0
with nogil:
iop = InplaceOps()
iop += Arg()
r0 = iop.val
return
cdef cypclass Call:
Value __call__(self):
return Value()
Value __call__(self, Arg a):
return Value()
def test_call():
"""
>>> test_call()
Arg destroyed
Value destroyed
Value destroyed
"""
cdef Value r0, r1
with nogil:
call = Call()
r0 = call()
r1 = call(Arg())
return
cdef cypclass Index:
__dealloc__(self) with gil:
print("Index destroyed")
cdef cypclass Subscript:
Value value
Index index
__init__(self):
self.value = NULL
self.index = NULL
Value __getitem__(const self, Index index):
if self.index is index:
return value
return NULL
void __setitem__(self, Index index, Value value):
self.index = index
self.value = value
def test_subscript():
"""
>>> test_subscript()
Index destroyed
Value destroyed
"""
cdef Value r0
with nogil:
s = Subscript()
index = Index()
value = Value()
s[index] = value
return
cdef cypclass Unop:
Value __pos__(self):
return Value()
def test_unop():
"""
>>> test_unop()
Value destroyed
"""
cdef Value r0
with nogil:
un = Unop()
r0 = +un
return
def test_typecast():
"""
>>> test_typecast()
Value destroyed
"""
with nogil:
r1 = <cyobject> Value()
return
\ No newline at end of file
......@@ -139,16 +139,16 @@ cdef object cyobject_to_pyobject(Refcounted r):
cdef Refcounted pyobject_to_cyobject(object o):
return o
cdef void consume_cyobject(Refcounted r):
cdef void recover_cyobject(Refcounted r):
pass
def consume_wrapped_cyobject(Refcounted r):
def recover_wrapped_cyobject(Refcounted r):
pass
def wrapped_cyobject_to_pyobject(Refcounted r):
return r
def consume_wrapped_cyobject_with_generic_args(Refcounted r, **kwargs):
def recover_wrapped_cyobject_with_generic_args(Refcounted r, **kwargs):
pass
def wrapped_cyobject_to_pyobject_with_generic_args(Refcounted r, dummy=2, unused="unused"):
......@@ -169,39 +169,39 @@ def test_recfcount_round_trip_conversions():
return Cy_GETREF(r)
def test_recfcount_consume_cyobject():
def test_recfcount_recover_cyobject():
"""
>>> test_recfcount_consume_cyobject()
>>> test_recfcount_recover_cyobject()
2
"""
cdef Refcounted r = Refcounted()
for i in range(10):
consume_cyobject(r)
recover_cyobject(r)
return Cy_GETREF(r)
def test_recfcount_consume_converted_cyobject():
def test_recfcount_recover_converted_cyobject():
"""
>>> test_recfcount_consume_converted_cyobject()
>>> test_recfcount_recover_converted_cyobject()
2
"""
cdef Refcounted r = Refcounted()
for i in range(10):
consume_cyobject(<object> r)
recover_cyobject(<object> r)
return Cy_GETREF(r)
def test_recfcount_consume_wrapped_cyobject():
def test_recfcount_recover_wrapped_cyobject():
"""
>>> test_recfcount_consume_wrapped_cyobject()
>>> test_recfcount_recover_wrapped_cyobject()
2
"""
cdef Refcounted r = Refcounted()
for i in range(10):
consume_wrapped_cyobject(r)
recover_wrapped_cyobject(r)
return Cy_GETREF(r)
......@@ -217,15 +217,15 @@ def test_recfcount_convert_wrapped_cyobject():
return Cy_GETREF(r)
def test_recfcount_consume_wrapped_cyobject_with_generic_args():
def test_recfcount_recover_wrapped_cyobject_with_generic_args():
"""
>>> test_recfcount_consume_wrapped_cyobject_with_generic_args()
>>> test_recfcount_recover_wrapped_cyobject_with_generic_args()
2
"""
cdef Refcounted r = Refcounted()
for i in range(10):
consume_wrapped_cyobject_with_generic_args(r)
recover_wrapped_cyobject_with_generic_args(r)
return Cy_GETREF(r)
......
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_recover_name():
"""
>>> test_recover_name()
Refcounted destroyed
0
"""
r0 = Refcounted()
if Cy_GETREF(r0) != 2:
return -1
cdef Refcounted r1 = recover r0
if r0 is not NULL:
return -2
if Cy_GETREF(r1) != 2:
return -3
return 0
def test_recover_iso_name():
"""
>>> test_recover_iso_name()
Refcounted destroyed
0
"""
cdef iso Refcounted r0 = recover Refcounted()
cdef Refcounted r1 = recover r0
if r0 is not NULL:
return -2
if Cy_GETREF(r1) != 2:
return -3
return 0
def test_recover_and_drop_name():
"""
>>> test_recover_and_drop_name()
Refcounted destroyed
recovered
0
"""
r = Refcounted()
if Cy_GETREF(r) != 2:
return -1
recover r
print("recovered")
if r is not NULL:
return -2
return 0
cdef cypclass DoubleRefcounted(Refcounted):
DoubleRefcounted get_self(self):
return self
def test_recover_and_drop_aliased_temporary():
"""
>>> test_recover_and_drop_aliased_temporary()
'recover' operand is not isolated
Refcounted destroyed
0
"""
r = DoubleRefcounted()
if Cy_GETREF(r) != 2:
return -1
try:
recover r.get_self()
return -2
except TypeError as e:
print(e)
if Cy_GETREF(r) != 2:
return -3
return 0
def test_recover_and_drop_cast_aliased_temporary():
"""
>>> test_recover_and_drop_cast_aliased_temporary()
'recover' operand is not isolated
Refcounted destroyed
0
"""
r = DoubleRefcounted()
if Cy_GETREF(r) != 2:
return -1
try: