Commit 5f192afb authored by Xavier Thompson's avatar Xavier Thompson

Use scope-bound lock guards to manage cypclass locks

parent 1bb76726
...@@ -14068,6 +14068,7 @@ class CoerceToTempNode(CoercionNode): ...@@ -14068,6 +14068,7 @@ class CoerceToTempNode(CoercionNode):
class CoerceToLockedTempNode(CoerceToTempNode): class CoerceToLockedTempNode(CoerceToTempNode):
# rlock_only boolean # rlock_only boolean
# guard_code used internally
def __init__(self, arg, env=None, rlock_only=False): def __init__(self, arg, env=None, rlock_only=False):
self.rlock_only = rlock_only self.rlock_only = rlock_only
...@@ -14089,16 +14090,20 @@ class CoerceToLockedTempNode(CoerceToTempNode): ...@@ -14089,16 +14090,20 @@ class CoerceToLockedTempNode(CoerceToTempNode):
context = code.get_string_const(StringEncoding.EncodedString(context)) context = code.get_string_const(StringEncoding.EncodedString(context))
else: else:
context = "NULL" context = "NULL"
# Create a scope to use scope bound resource management (RAII).
code.putln("{")
# Each lock guard has its onw scope, so a prefix is enough to prevent name collisions
guard_code = "%sguard" % Naming.cypclass_lock_guard_prefix
if self.rlock_only: if self.rlock_only:
code.putln("Cy_RLOCK_CONTEXT(%s, %s);" % (self.result(), context)) code.putln("Cy_rlock_guard %s(%s, %s);" % (guard_code, self.result(), context))
else: else:
code.putln("Cy_WLOCK_CONTEXT(%s, %s);" % (self.result(), context)) code.putln("Cy_wlock_guard %s(%s, %s);" % (guard_code, self.result(), context))
def generate_disposal_code(self, code): def generate_disposal_code(self, code):
if self.rlock_only: # Close the scope to release the lock.
code.putln("Cy_UNRLOCK(%s);" % self.result()) code.putln("}")
else:
code.putln("Cy_UNWLOCK(%s);" % self.result())
super(CoerceToLockedTempNode, self).generate_disposal_code(code) super(CoerceToLockedTempNode, self).generate_disposal_code(code)
......
...@@ -58,6 +58,7 @@ convert_func_prefix = pyrex_prefix + "convert_" ...@@ -58,6 +58,7 @@ convert_func_prefix = pyrex_prefix + "convert_"
closure_scope_prefix = pyrex_prefix + "scope_" closure_scope_prefix = pyrex_prefix + "scope_"
closure_class_prefix = pyrex_prefix + "scope_struct_" closure_class_prefix = pyrex_prefix + "scope_struct_"
lambda_func_prefix = pyrex_prefix + "lambda_" lambda_func_prefix = pyrex_prefix + "lambda_"
cypclass_lock_guard_prefix = pyrex_prefix + "cy_lock_"
module_is_main = pyrex_prefix + "module_is_main" module_is_main = pyrex_prefix + "module_is_main"
defaults_struct_prefix = pyrex_prefix + "defaults" defaults_struct_prefix = pyrex_prefix + "defaults"
dynamic_args_cname = pyrex_prefix + "dynamic_args" dynamic_args_cname = pyrex_prefix + "dynamic_args"
......
...@@ -8579,15 +8579,21 @@ class LockCypclassNode(StatNode): ...@@ -8579,15 +8579,21 @@ class LockCypclassNode(StatNode):
context = code.get_string_const(EncodedString(context)) context = code.get_string_const(EncodedString(context))
else: else:
context = "NULL" context = "NULL"
lock_code = "Cy_%s_CONTEXT(%s, %s);" % (self.state[:-2].upper(), self.obj.result(), context)
code.putln(lock_code)
self.body.generate_execution_code(code) # Create a scope to use scope bound resource management (RAII).
code.putln("{")
# Each lock guard has its onw scope, so a prefix is enough to prevent name collisions
guard_code = "%sguard" % Naming.cypclass_lock_guard_prefix
if self.state == "rlocked": if self.state == "rlocked":
code.putln("Cy_UNRLOCK(%s);" % self.obj.result()) code.putln("Cy_rlock_guard %s(%s, %s);" % (guard_code, self.obj.result(), context))
elif self.state == "wlocked": elif self.state == "wlocked":
code.putln("Cy_UNWLOCK(%s);" % self.obj.result()) code.putln("Cy_wlock_guard %s(%s ,%s);" % (guard_code, self.obj.result(), context))
self.body.generate_execution_code(code)
# Close the scope to release the lock.
code.putln("}")
def cython_view_utility_code(): def cython_view_utility_code():
......
...@@ -88,6 +88,48 @@ ...@@ -88,6 +88,48 @@
int CyObject_TRYWLOCK(); int CyObject_TRYWLOCK();
}; };
class Cy_rlock_guard {
CyObject* o;
public:
Cy_rlock_guard(CyObject* o, const char * context) : o(o) {
if (o != NULL) {
o->CyObject_RLOCK(context);
}
else {
fprintf(stderr, "ERROR: trying to rlock NULL !\n");
}
}
~Cy_rlock_guard() {
if (this->o != NULL) {
this->o->CyObject_UNRLOCK();
}
else {
fprintf(stderr, "ERROR: trying to unrlock NULL !\n");
}
}
};
class Cy_wlock_guard {
CyObject* o;
public:
Cy_wlock_guard(CyObject* o, const char * context) : o(o) {
if (o != NULL) {
o->CyObject_WLOCK(context);
}
else {
fprintf(stderr, "ERROR: trying to wlock NULL !\n");
}
}
~Cy_wlock_guard() {
if (this->o != NULL) {
this->o->CyObject_UNWLOCK();
}
else {
fprintf(stderr, "ERROR: trying to unwlock NULL !\n");
}
}
};
/* All this is made available by member injection inside the module scope */ /* All this is made available by member injection inside the module scope */
struct ActhonResultInterface : public CyObject { struct ActhonResultInterface : public CyObject {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment