[vala] Support locks with static fields



commit 0154b1a6909c76d41b47a6dca011d078da316c14
Author: Levi Bard <taktaktaktaktaktaktaktaktaktak gmail com>
Date:   Mon Jul 27 23:11:30 2009 +0200

    Support locks with static fields
    
    Fixes bug 537461.

 codegen/valaccodebasemodule.vala |   62 +++++++++++++++++++++++++++++-------
 codegen/valagtypemodule.vala     |   65 ++++++++++++++++++++++---------------
 tests/objects/fields.test        |   16 +++++++--
 vala/valamemberaccess.vala       |   20 +-----------
 vala/valasymbol.vala             |   44 +++++++++++++++++++++++++
 5 files changed, 146 insertions(+), 61 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index bc6adf4..14b35f3 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -747,16 +747,29 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		/* stuff meant for all lockable members */
 		if (m is Lockable && ((Lockable) m).get_lock_used ()) {
 			CCodeExpression l = new CCodeIdentifier ("self");
-			l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (m));
+			CCodeFragment init_fragment = class_init_fragment;
+			CCodeFragment finalize_fragment = class_finalize_fragment;
+
+			if (m.is_instance_member ()) {
+				l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (m.name));
+				init_fragment = instance_init_fragment;
+				finalize_fragment = instance_finalize_fragment;
+			} else if (m.is_class_member ()) {
+				TypeSymbol parent = (TypeSymbol)m.parent_symbol;
+				l = new CCodeIdentifier ("%s_GET_CLASS_PRIVATE(%s)".printf(parent.get_upper_case_cname (), parent.get_type_id ()));
+				l = new CCodeMemberAccess.pointer (l, get_symbol_lock_name (m.name));
+			} else {
+				l = new CCodeIdentifier (get_symbol_lock_name ("%s_%s".printf(m.parent_symbol.get_lower_case_cname (), m.name)));
+			}
 
 			var initf = new CCodeFunctionCall (new CCodeIdentifier (mutex_type.default_construction_method.get_cname ()));
 			initf.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
-			instance_init_fragment.append (new CCodeExpressionStatement (initf));
+			init_fragment.append (new CCodeExpressionStatement (initf));
 
-			if (instance_finalize_fragment != null) {
+			if (finalize_fragment != null) {
 				var fc = new CCodeFunctionCall (new CCodeIdentifier ("g_static_rec_mutex_free"));
 				fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
-				instance_finalize_fragment.append (new CCodeExpressionStatement (fc));
+				finalize_fragment.append (new CCodeExpressionStatement (fc));
 			}
 		}
 	}
@@ -816,6 +829,20 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		}
 		decl_space.add_type_member_declaration (cdecl);
 
+		if (f.get_lock_used ()) {
+			// Declare mutex for static member
+			var flock = new CCodeDeclaration (mutex_type.get_cname ());
+			var flock_decl =  new CCodeVariableDeclarator (get_symbol_lock_name (f.get_cname ()), new CCodeConstant ("{0}"));
+			flock.add_declarator (flock_decl);
+
+			if (f.is_private_symbol ()) {
+				flock.modifiers = CCodeModifiers.STATIC;
+			} else {
+				flock.modifiers = CCodeModifiers.EXTERN;
+			}
+			decl_space.add_type_member_declaration (flock);
+		}
+
 		if (f.field_type is ArrayType && !f.no_array_length) {
 			var array_type = (ArrayType) f.field_type;
 
@@ -2494,8 +2521,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		}
 	}
 
-	public string get_symbol_lock_name (Symbol sym) {
-		return "__lock_%s".printf (sym.name);
+	public string get_symbol_lock_name (string symname) {
+		return "__lock_%s".printf (symname);
 	}
 
 	public override void visit_lock_statement (LockStatement stmt) {
@@ -2503,15 +2530,26 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		CCodeExpression l = null;
 		CCodeFunctionCall fc;
 		var inner_node = ((MemberAccess)stmt.resource).inner;
+		var member = (Member)stmt.resource.symbol_reference;
+		var parent = (TypeSymbol) stmt.resource.symbol_reference.parent_symbol;
 		
-		if (inner_node  == null) {
-			l = new CCodeIdentifier ("self");
-		} else if (stmt.resource.symbol_reference.parent_symbol != current_type_symbol) {
-			 l = new InstanceCast ((CCodeExpression) inner_node.ccodenode, (TypeSymbol) stmt.resource.symbol_reference.parent_symbol);
+		if (member.is_instance_member ()) {
+			if (inner_node  == null) {
+				l = new CCodeIdentifier ("self");
+			} else if (stmt.resource.symbol_reference.parent_symbol != current_type_symbol) {
+				 l = new InstanceCast ((CCodeExpression) inner_node.ccodenode, parent);
+			} else {
+				l = (CCodeExpression) inner_node.ccodenode;
+			}
+
+			l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (stmt.resource.symbol_reference.name));
+		} else if (member.is_class_member ()) {
+			l = new CCodeIdentifier ("%s_GET_CLASS_PRIVATE(%s)".printf(parent.get_upper_case_cname (), parent.get_type_id ()));
+			l = new CCodeMemberAccess.pointer (l, get_symbol_lock_name (stmt.resource.symbol_reference.name));
 		} else {
-			l = (CCodeExpression) inner_node.ccodenode;
+			string lock_name = "%s_%s".printf(parent.get_lower_case_cname (), stmt.resource.symbol_reference.name);
+			l = new CCodeIdentifier (get_symbol_lock_name (lock_name));
 		}
-		l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (stmt.resource.symbol_reference));
 		
 		fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ()));
 		fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index 7ac0ed2..e5bf70e 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -271,31 +271,33 @@ internal class Vala.GTypeModule : GErrorModule {
 				field_ctype = "volatile " + field_ctype;
 			}
 
-			if (f.binding == MemberBinding.INSTANCE && f.access != SymbolAccessibility.PRIVATE)  {
-				generate_type_declaration (f.field_type, decl_space);
+			if (f.access != SymbolAccessibility.PRIVATE) {
+				if (f.binding == MemberBinding.INSTANCE) {
+					generate_type_declaration (f.field_type, decl_space);
 
-				instance_struct.add_field (field_ctype, f.get_cname ());
-				if (f.field_type is ArrayType && !f.no_array_length) {
-					// create fields to store array dimensions
-					var array_type = (ArrayType) f.field_type;
-					var len_type = int_type.copy ();
+					instance_struct.add_field (field_ctype, f.get_cname ());
+					if (f.field_type is ArrayType && !f.no_array_length) {
+						// create fields to store array dimensions
+						var array_type = (ArrayType) f.field_type;
+						var len_type = int_type.copy ();
 
-					for (int dim = 1; dim <= array_type.rank; dim++) {
-						instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
-					}
+						for (int dim = 1; dim <= array_type.rank; dim++) {
+							instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
+						}
 
-					if (array_type.rank == 1 && f.is_internal_symbol ()) {
-						instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
-					}
-				} else if (f.field_type is DelegateType) {
-					var delegate_type = (DelegateType) f.field_type;
-					if (delegate_type.delegate_symbol.has_target) {
-						// create field to store delegate target
-						instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
+						if (array_type.rank == 1 && f.is_internal_symbol ()) {
+							instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
+						}
+					} else if (f.field_type is DelegateType) {
+						var delegate_type = (DelegateType) f.field_type;
+						if (delegate_type.delegate_symbol.has_target) {
+							// create field to store delegate target
+							instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
+						}
 					}
+				} else if (f.binding == MemberBinding.CLASS) {
+					type_struct.add_field (field_ctype, f.get_cname ());
 				}
-			} else if (f.binding == MemberBinding.CLASS && f.access != SymbolAccessibility.PRIVATE)  {
-				type_struct.add_field (field_ctype, f.get_cname ());
 			}
 		}
 
@@ -331,6 +333,8 @@ internal class Vala.GTypeModule : GErrorModule {
 		}
 
 		bool is_gtypeinstance = !cl.is_compact;
+		bool has_instance_locks = false;
+		bool has_class_locks = false;
 
 		var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
 		var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ()));
@@ -384,16 +388,25 @@ internal class Vala.GTypeModule : GErrorModule {
 				}
 
 				if (f.get_lock_used ()) {
+					has_instance_locks = true;
+					// add field for mutex
+					instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f.name));
+				}
+			} else if (f.binding == MemberBinding.CLASS) {
+				if (f.access == SymbolAccessibility.PRIVATE) {
+					type_priv_struct.add_field (field_ctype, f.get_cname ());
+				}
+
+				if (f.get_lock_used ()) {
+					has_class_locks = true;
 					// add field for mutex
-					instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f));
+					type_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f.get_cname ()));
 				}
-			} else if (f.binding == MemberBinding.CLASS && f.access == SymbolAccessibility.PRIVATE)  {
-				type_priv_struct.add_field (field_ctype, f.get_cname ());
 			}
 		}
 
 		if (is_gtypeinstance) {
-			if (cl.has_class_private_fields) {
+			if (cl.has_class_private_fields || has_class_locks) {
 				decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ()))));
 				var cdecl = new CCodeDeclaration ("GQuark");
 				cdecl.add_declarator (new CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0")));
@@ -402,13 +415,13 @@ internal class Vala.GTypeModule : GErrorModule {
 			}
 
 			/* only add the *Private struct if it is not empty, i.e. we actually have private data */
-			if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
+			if (cl.has_private_fields || cl.get_type_parameters ().size > 0 || has_instance_locks) {
 				decl_space.add_type_definition (instance_priv_struct);
 				var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_type_id (), cl.get_cname ());
 				decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
 			}
 
-			if (cl.has_class_private_fields) {
+			if (cl.has_class_private_fields || has_class_locks) {
 				decl_space.add_type_member_declaration (type_priv_struct);
 
 				var macro = "((%sClassPrivate *) g_type_get_qdata (type, _vala_%s_class_private_quark))".printf (cl.get_cname(), cl.get_lower_case_cname ());
diff --git a/tests/objects/fields.test b/tests/objects/fields.test
index f347fbb..7690b6e 100644
--- a/tests/objects/fields.test
+++ b/tests/objects/fields.test
@@ -35,10 +35,18 @@ class Maman.Bar : Foo {
 		public_base_field = 9;
 		public_field = 10;
 		private_field = 11;
-		private_static_field = 12;
-		public_static_field = 13;
-		private_class_field = 14;
-		public_class_field = 15;
+		lock (private_static_field) {
+			private_static_field = 12;
+		}
+		lock (public_static_field) {
+			public_static_field = 13;
+		}
+		lock (private_class_field) {
+			private_class_field = 14;
+		}
+		lock (public_class_field) {
+			public_class_field = 15;
+		}
 		stdout.printf (" %d %d %d %d %d %d %d", public_base_field, public_field,
 		               private_field, private_static_field, public_static_field, 
 					   private_class_field, public_class_field);
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index aa44c1e..3ce7399 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -133,25 +133,7 @@ public class Vala.MemberAccess : Expression {
 	}
 
 	public override string to_string () {
-		bool instance = true;
-		if (symbol_reference is Field) {
-			var f = (Field) symbol_reference;
-			instance = (f.binding == MemberBinding.INSTANCE);
-		} else if (symbol_reference is Method) {
-			var m = (Method) symbol_reference;
-			if (!(m is CreationMethod)) {
-				instance = (m.binding == MemberBinding.INSTANCE);
-			}
-		} else if (symbol_reference is Property) {
-			var prop = (Property) symbol_reference;
-			instance = (prop.binding == MemberBinding.INSTANCE);
-		} else if (symbol_reference is EnumValue) {
-			instance = false;
-		} else if (symbol_reference is ErrorCode) {
-			instance = false;
-		}
-
-		if (instance) {
+		if (symbol_reference.is_instance_member ()) {
 			if (inner == null) {
 				return member_name;
 			} else {
diff --git a/vala/valasymbol.vala b/vala/valasymbol.vala
index 61a1c0a..ca54bd6 100644
--- a/vala/valasymbol.vala
+++ b/vala/valasymbol.vala
@@ -313,6 +313,50 @@ public abstract class Vala.Symbol : CodeNode {
 		// if this is a public symbol, it's equally accessible as the parent symbol
 		return parent_symbol.get_top_accessible_scope (is_internal);
 	}
+
+	public virtual bool is_instance_member () {
+		bool instance = true;
+		if (this is Field) {
+			var f = (Field) this;
+			instance = (f.binding == MemberBinding.INSTANCE);
+		} else if (this is Method) {
+			var m = (Method) this;
+			if (!(m is CreationMethod)) {
+				instance = (m.binding == MemberBinding.INSTANCE);
+			}
+		} else if (this is Property) {
+			var prop = (Property) this;
+			instance = (prop.binding == MemberBinding.INSTANCE);
+		} else if (this is EnumValue) {
+			instance = false;
+		} else if (this is ErrorCode) {
+			instance = false;
+		}
+
+		return instance;
+	}
+
+	public virtual bool is_class_member () {
+		bool isclass = true;
+		if (this is Field) {
+			var f = (Field) this;
+			isclass = (f.binding == MemberBinding.CLASS);
+		} else if (this is Method) {
+			var m = (Method) this;
+			if (!(m is CreationMethod)) {
+				isclass = (m.binding == MemberBinding.CLASS);
+			}
+		} else if (this is Property) {
+			var prop = (Property) this;
+			isclass = (prop.binding == MemberBinding.CLASS);
+		} else if (this is EnumValue) {
+			isclass = false;
+		} else if (this is ErrorCode) {
+			isclass = false;
+		}
+
+		return isclass;
+	}
 }
 
 public enum Vala.SymbolAccessibility {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]