From a265bc697a9b590bb5c9bd25563a09924bd7f6a3 Mon Sep 17 00:00:00 2001 From: Raffaele Sandrini Date: Wed, 27 Sep 2006 12:37:03 +0000 Subject: [PATCH] add threading and assorted structures add an additional abstraction for 2006-09-27 Raffaele Sandrini * vapi/glib-2.0.vala: add threading and assorted structures * vala/valamember.vala: add an additional abstraction for all members of a class * vala/valalockstatement.vala, vala/valacodegenerator.vala, vala/scanner.l, vala/valasemanticanalyzer.vala, vala/valalockable.vala, vala/parser.y, vala/valacodevisitor.vala: add lock feature to vala * vala/valamethod.vala, vala/valafield.vala, vala/valaconstant.vala, vala/valasignal.vala, vala/valaproperty.vala: make those members lockable * vala/valacodegenerator.vala: use member abstraction to simlify field initialisation and destruction * vala/valacodegenerator.vala: introduce new C macros VALA_FREE_CHECKED and VALA_FREE_UNCHECKED to make safe freeing code nicer * vala/vala.h: update and bring arraycreationexpression in order * vala/Makefile.am: update svn path=/trunk/; revision=129 --- vala/ChangeLog | 19 ++++++ vala/vala/Makefile.am | 12 ++++ vala/vala/parser.y | 13 ++++ vala/vala/scanner.l | 1 + vala/vala/vala.h | 3 +- vala/vala/valacodegenerator.vala | 127 ++++++++++++++++++++++++++---------- vala/vala/valacodevisitor.vala | 16 +++++ vala/vala/valaconstant.vala | 16 ++++- vala/vala/valafield.vala | 14 +++- vala/vala/valalockable.vala | 36 ++++++++++ vala/vala/valalockstatement.vala | 50 ++++++++++++++ vala/vala/valamember.vala | 30 +++++++++ vala/vala/valamethod.vala | 2 +- vala/vala/valaproperty.vala | 13 +++- vala/vala/valasemanticanalyzer.vala | 36 ++++++++++ vala/vala/valasignal.vala | 14 +++- vala/vapi/glib-2.0.vala | 49 +++++++++++++- 17 files changed, 409 insertions(+), 42 deletions(-) create mode 100644 vala/vala/valalockable.vala create mode 100644 vala/vala/valalockstatement.vala create mode 100644 vala/vala/valamember.vala diff --git a/vala/ChangeLog b/vala/ChangeLog index 54d913e..8320f94 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,22 @@ +2006-09-27 Raffaele Sandrini + + * vapi/glib-2.0.vala: add threading and assorted structures + * vala/valamember.vala: add an additional abstraction for all members + of a class + * vala/valalockstatement.vala, vala/valacodegenerator.vala, + vala/scanner.l, vala/valasemanticanalyzer.vala, + vala/valalockable.vala, vala/parser.y, vala/valacodevisitor.vala: + add lock feature to vala + * vala/valamethod.vala, vala/valafield.vala, vala/valaconstant.vala, + vala/valasignal.vala, vala/valaproperty.vala: make those members + lockable + * vala/valacodegenerator.vala: use member abstraction to simlify field + initialisation and destruction + * vala/valacodegenerator.vala: introduce new C macros VALA_FREE_CHECKED + and VALA_FREE_UNCHECKED to make safe freeing code nicer + * vala/vala.h: update and bring arraycreationexpression in order + * vala/Makefile.am: update + 2006-09-27 Jürg Billeter * vapi/glib-2.0.vala: add Process struct with spawn functions diff --git a/vala/vala/Makefile.am b/vala/vala/Makefile.am index 8ec3b25..6f31e97 100644 --- a/vala/vala/Makefile.am +++ b/vala/vala/Makefile.am @@ -169,6 +169,15 @@ libvala_la_SOURCES = \ valalocalvariabledeclaration.c \ valalocalvariabledeclaration.h \ valalocalvariabledeclaration.vala \ + valalockable.c \ + valalockable.h \ + valalockable.vala \ + valalockstatement.c \ + valalockstatement.h \ + valalockstatement.vala \ + valamember.c \ + valamember.h \ + valamember.vala \ valamemberaccess.c \ valamemberaccess.h \ valamemberaccess.vala \ @@ -343,6 +352,9 @@ valainclude_HEADERS = \ valaliteral.h \ valaliteralexpression.h \ valalocalvariabledeclaration.h \ + valalockable.h \ + valamember.h \ + valalockstatement.h \ valamemberaccess.h \ valamemberaccessibility.h \ valamemorymanager.h \ diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 6af4151..41ae4fb 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -170,6 +170,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %token IN "in" %token INTERFACE "interface" %token IS "is" +%token LOCK "lock" %token NAMESPACE "namespace" %token NEW "new" %token VALA_NULL "null" @@ -282,6 +283,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type break_statement %type continue_statement %type return_statement +%type lock_statement %type namespace_declaration %type opt_name_specifier %type name_specifier @@ -1224,6 +1226,7 @@ embedded_statement | selection_statement | iteration_statement | jump_statement + | lock_statement ; block @@ -1686,6 +1689,16 @@ return_statement } ; +lock_statement + : comment LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement + { + ValaSourceReference *src = src_com(@4, $1); + $$ = VALA_STATEMENT (vala_lock_statement_new ($4, $6, src)); + g_object_unref (src); + g_object_unref ($4); + g_object_unref ($6); + } + namespace_declaration : comment opt_attributes NAMESPACE IDENTIFIER { diff --git a/vala/vala/scanner.l b/vala/vala/scanner.l index e6c17ea..cf147b7 100644 --- a/vala/vala/scanner.l +++ b/vala/vala/scanner.l @@ -171,6 +171,7 @@ literal ({integer_literal}|{real_literal}|{character_literal}|{string_literal "virtual" { uploc; return VIRTUAL; } "weak" { uploc; return WEAK; } "while" { uploc; return WHILE; } +"lock" { uploc; return LOCK; } {real_literal} { uploc; yylval->str = g_strdup (yytext); return REAL_LITERAL; } {integer_literal} { uploc; yylval->str = g_strdup (yytext); return INTEGER_LITERAL; } diff --git a/vala/vala/vala.h b/vala/vala/vala.h index 4dc05e1..7177791 100644 --- a/vala/vala/vala.h +++ b/vala/vala/vala.h @@ -1,3 +1,4 @@ +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -65,4 +67,3 @@ #include #include #include -#include diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 4598e52..f6d60ec 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -37,6 +37,7 @@ public class Vala.CodeGenerator : CodeVisitor { Symbol root_symbol; Symbol current_symbol; Symbol current_type_symbol; + Class current_class; CCodeFragment header_begin; CCodeFragment header_type_declaration; @@ -46,6 +47,8 @@ public class Vala.CodeGenerator : CodeVisitor { CCodeFragment source_include_directives; CCodeFragment source_type_member_declaration; CCodeFragment source_type_member_definition; + CCodeFragment instance_init_fragment; + CCodeFragment instance_dispose_fragment; CCodeStruct instance_struct; CCodeStruct type_struct; @@ -78,6 +81,7 @@ public class Vala.CodeGenerator : CodeVisitor { TypeReference double_type; DataType list_type; DataType slist_type; + TypeReference mutex_type; public construct (bool manage_memory = true) { memory_management = manage_memory; @@ -141,6 +145,9 @@ public class Vala.CodeGenerator : CodeVisitor { list_type = (DataType) glib_ns.lookup ("List").node; slist_type = (DataType) glib_ns.lookup ("SList").node; + + mutex_type = new TypeReference (); + mutex_type.data_type = (DataType) glib_ns.lookup ("Mutex").node; /* we're only interested in non-pkg source files */ var source_files = context.get_source_files (); @@ -216,6 +223,10 @@ public class Vala.CodeGenerator : CodeVisitor { } } } + + /* generate hardcoded "well-known" macros */ + source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))")); + source_begin.append (new CCodeMacroReplacement ("VALA_FREE_UNCHECKED(o,f)", "((o) = (f (o), NULL))")); } private static ref string get_define_for_filename (string! filename) { @@ -298,12 +309,15 @@ public class Vala.CodeGenerator : CodeVisitor { public override void visit_begin_class (Class! cl) { current_symbol = cl.symbol; current_type_symbol = cl.symbol; + current_class = cl; instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ())); type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ())); instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ())); prop_enum = new CCodeEnum (); prop_enum.add_value ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)), null); + instance_init_fragment = new CCodeFragment (); + instance_dispose_fragment = new CCodeFragment (); header_type_declaration.append (new CCodeNewline ()); @@ -370,6 +384,7 @@ public class Vala.CodeGenerator : CodeVisitor { source_type_member_definition.append (type_fun); current_type_symbol = null; + current_class = null; } private void add_class_init_function (Class! cl) { @@ -579,24 +594,7 @@ public class Vala.CodeGenerator : CodeVisitor { init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall))); } - var fields = cl.get_fields (); - foreach (Field f in fields) { - if (f.initializer != null) { - ref CCodeExpression lhs = null; - if (f.instance) { - if (f.access == MemberAccessibility.PRIVATE) { - lhs = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), f.get_cname ()); - } else { - lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ()); - } - } /* else { - lhs = new CCodeIdentifier ("%s_%s".printf (cl.get_lower_case_cname (null), f.get_cname ())); - } */ - if (lhs != null) { - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (lhs, (CCodeExpression) f.initializer.ccodenode))); - } - } - } + init_block.add_statement (instance_init_fragment); var init_sym = cl.symbol.lookup ("init"); if (init_sym != null) { @@ -626,21 +624,7 @@ public class Vala.CodeGenerator : CodeVisitor { cblock.add_statement (cdecl); - - var fields = cl.get_fields (); - foreach (Field f in fields) { - if (f.instance && f.type_reference.takes_ownership) { - var cself = new CCodeIdentifier ("self"); - CCodeExpression cstruct = cself; - if (f.access == MemberAccessibility.PRIVATE) { - cstruct = new CCodeMemberAccess.pointer (cself, "priv"); - } - var cfield = new CCodeMemberAccess.pointer (cstruct, f.get_cname ()); - - cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (cfield, f.type_reference))); - } - } - + cblock.add_statement (instance_dispose_fragment); cdecl = new CCodeDeclaration ("%sClass *".printf (cl.get_cname ())); cdecl.add_declarator (new CCodeVariableDeclarator ("klass")); @@ -880,6 +864,29 @@ public class Vala.CodeGenerator : CodeVisitor { source_type_member_declaration.append (ctypedef); } } + + public override void visit_member (Member! m) { + /* stuff meant for all lockable members */ + if (m is Lockable && ((Lockable)m).get_lock_used ()) { + instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (m.symbol)); + + instance_init_fragment.append ( + new CCodeExpressionStatement ( + new CCodeAssignment ( + new CCodeMemberAccess.pointer ( + new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), + get_symbol_lock_name (m.symbol)), + new CCodeFunctionCall (new CCodeIdentifier (((Struct)mutex_type.data_type).default_construction_method.get_cname ()))))); + + var fc = new CCodeFunctionCall (new CCodeIdentifier ("VALA_FREE_CHECKED")); + fc.add_argument ( + new CCodeMemberAccess.pointer ( + new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), + get_symbol_lock_name (m.symbol))); + fc.add_argument (new CCodeIdentifier (mutex_type.data_type.get_free_function ())); + instance_dispose_fragment.append (new CCodeExpressionStatement (fc)); + } + } public override void visit_constant (Constant! c) { if (c.symbol.parent_symbol.node is DataType) { @@ -901,11 +908,17 @@ public class Vala.CodeGenerator : CodeVisitor { } public override void visit_field (Field! f) { + CCodeExpression lhs = null; + if (f.access != MemberAccessibility.PRIVATE) { instance_struct.add_field (f.type_reference.get_cname (), f.get_cname ()); + if (f.instance) { + lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ()); + } } else if (f.access == MemberAccessibility.PRIVATE) { if (f.instance) { instance_priv_struct.add_field (f.type_reference.get_cname (), f.get_cname ()); + lhs = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), f.get_cname ()); } else { if (f.symbol.parent_symbol.node is DataType) { var t = (DataType) f.symbol.parent_symbol.node; @@ -920,6 +933,16 @@ public class Vala.CodeGenerator : CodeVisitor { } } } + + if (f.instance) { + if (f.initializer != null) { + instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, (CCodeExpression) f.initializer.ccodenode))); + } + + if (f.type_reference.takes_ownership) { + instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.type_reference))); + } + } } public override void visit_begin_method (Method! m) { @@ -1899,6 +1922,44 @@ public class Vala.CodeGenerator : CodeVisitor { } } + private ref string get_symbol_lock_name (Symbol! sym) { + return "__lock_%s".printf (sym.name); + } + + /** + * Visit operation called for lock statements. + * + * @param stmt a lock statement + */ + public override void visit_lock_statement (LockStatement! stmt) { + var cn = new CCodeFragment (); + CCodeExpression l = null; + CCodeFunctionCall fc; + var inner_node = ((MemberAccess)stmt.resource).inner; + + if (inner_node == null) { + l = new CCodeIdentifier ("self"); + } else if (stmt.resource.symbol_reference.parent_symbol.node != current_class) { + l = new CCodeFunctionCall (new CCodeIdentifier (((DataType) stmt.resource.symbol_reference.parent_symbol.node).get_upper_case_cname ())); + ((CCodeFunctionCall) l).add_argument ((CCodeExpression)inner_node.ccodenode); + } else { + l = (CCodeExpression)inner_node.ccodenode; + } + 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.data_type.symbol.lookup ("lock").node).get_cname ())); + fc.add_argument (l); + cn.append (new CCodeExpressionStatement (fc)); + + cn.append (stmt.body.ccodenode); + + fc = new CCodeFunctionCall (new CCodeIdentifier (((Method)mutex_type.data_type.symbol.lookup ("unlock").node).get_cname ())); + fc.add_argument (l); + cn.append (new CCodeExpressionStatement (fc)); + + stmt.ccodenode = cn; + } + /** * Visit operations called for array creation expresions. * diff --git a/vala/vala/valacodevisitor.vala b/vala/vala/valacodevisitor.vala index c88c754..6cc9529 100644 --- a/vala/vala/valacodevisitor.vala +++ b/vala/vala/valacodevisitor.vala @@ -170,6 +170,14 @@ public abstract class Vala.CodeVisitor { */ public virtual void visit_end_callback (Callback! cb) { } + + /** + * Visit operation called for Members. + * + * @param m a member + */ + public virtual void visit_member (Member! m) { + } /** * Visit operation called for constants. @@ -492,6 +500,14 @@ public abstract class Vala.CodeVisitor { } /** + * Visit operation called for lock statements before the body has been visited. + * + * @param stmt a lock statement + */ + public virtual void visit_lock_statement (LockStatement! stmt) { + } + + /** * Visit operation called at end of return statements. * * @param stmt a return statement diff --git a/vala/vala/valaconstant.vala b/vala/vala/valaconstant.vala index 08ae73d..e69c578 100644 --- a/vala/vala/valaconstant.vala +++ b/vala/vala/valaconstant.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a type member with a constant value. */ -public class Vala.Constant : CodeNode { +public class Vala.Constant : Member, Lockable { /** * The symbol name of this constant. */ @@ -50,6 +50,8 @@ public class Vala.Constant : CodeNode { public MemberAccessibility access; private string cname; + + private bool lock_used = false; /** * Creates a new constant. @@ -68,12 +70,14 @@ public class Vala.Constant : CodeNode { } public override void accept (CodeVisitor! visitor) { + visitor.visit_member (this); + type_reference.accept (visitor); if (initializer != null) { initializer.accept (visitor); } - + visitor.visit_constant (this); } @@ -94,4 +98,12 @@ public class Vala.Constant : CodeNode { } return cname; } + + public override bool get_lock_used () { + return lock_used; + } + + public override void set_lock_used (bool used) { + lock_used = used; + } } diff --git a/vala/vala/valafield.vala b/vala/vala/valafield.vala index 7612f49..f8c71a4 100644 --- a/vala/vala/valafield.vala +++ b/vala/vala/valafield.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a type or namespace field. */ -public class Vala.Field : CodeNode, Invokable { +public class Vala.Field : Member, Invokable, Lockable { /** * The symbol name of this field. */ @@ -65,6 +65,8 @@ public class Vala.Field : CodeNode, Invokable { private string cname; private bool _instance = true; + private bool lock_used = false; + /** * Creates a new field. * @@ -82,6 +84,8 @@ public class Vala.Field : CodeNode, Invokable { } public override void accept (CodeVisitor! visitor) { + visitor.visit_member (this); + type_reference.accept (visitor); if (initializer != null) { @@ -158,4 +162,12 @@ public class Vala.Field : CodeNode, Invokable { public override bool is_invokable () { return (type_reference.data_type is Callback); } + + public override bool get_lock_used () { + return lock_used; + } + + public override void set_lock_used (bool used) { + lock_used = used; + } } diff --git a/vala/vala/valalockable.vala b/vala/vala/valalockable.vala new file mode 100644 index 0000000..69bcae5 --- /dev/null +++ b/vala/vala/valalockable.vala @@ -0,0 +1,36 @@ +/* valalockable.vala + * + * Copyright (C) 2006 Raffaele Sandrini + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Raffaele Sandrini + */ + +/** + * Represents a lockable object. + */ +public interface Vala.Lockable { + /** + * Indicates a specific lockable object beeing actually locked somewhere. + */ + public abstract bool get_lock_used (); + + /** + * Set this lockable object as beeing locked somewhere. + */ + public abstract void set_lock_used (bool used); +} diff --git a/vala/vala/valalockstatement.vala b/vala/vala/valalockstatement.vala new file mode 100644 index 0000000..2fc537a --- /dev/null +++ b/vala/vala/valalockstatement.vala @@ -0,0 +1,50 @@ +/* valalockstatement.vala + * + * Copyright (C) 2006 Raffaele Sandrini + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Raffaele Sandrini + */ + +using GLib; + +/** + * Represents a lock statement e.g. "lock (a) { f(a) }". + */ +public class Vala.LockStatement : Statement { + /** + * Expression representing the resource to be locked. + */ + public Expression! resource { get; set construct; } + + /** + * The statement during its execution the resource is locked. + */ + public Statement! body { get; set construct; } + + public construct (Expression _resource, Statement _body, SourceReference source) { + resource = _resource; + body = _body; + source_reference = source; + } + + public override void accept (CodeVisitor! visitor) { + resource.accept (visitor); + body.accept (visitor); + visitor.visit_lock_statement (this); + } +} diff --git a/vala/vala/valamember.vala b/vala/vala/valamember.vala new file mode 100644 index 0000000..651a98b --- /dev/null +++ b/vala/vala/valamember.vala @@ -0,0 +1,30 @@ +/* valamember.vala + * + * Copyright (C) 2006 Raffaele Sandrini + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Raffaele Sandrini + */ + +/** + * Represents a general class member. + */ +public class Vala.Member : CodeNode { + public override void accept (CodeVisitor! visitor) { + visitor.visit_member (this); + } +} diff --git a/vala/vala/valamethod.vala b/vala/vala/valamethod.vala index 9ff7ae2..ffd7f01 100644 --- a/vala/vala/valamethod.vala +++ b/vala/vala/valamethod.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a type or namespace method. */ -public class Vala.Method : CodeNode, Invokable { +public class Vala.Method : Member, Invokable { /** * The symbol name of this method. */ diff --git a/vala/vala/valaproperty.vala b/vala/vala/valaproperty.vala index 69c2887..da3fe98 100644 --- a/vala/vala/valaproperty.vala +++ b/vala/vala/valaproperty.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a property declaration in the source code. */ -public class Vala.Property : CodeNode { +public class Vala.Property : Member, Lockable { /** * The property name. */ @@ -71,6 +71,8 @@ public class Vala.Property : CodeNode { */ public bool interface_only { get; set; } + private bool lock_used = false; + /** * Creates a new property. * @@ -90,6 +92,7 @@ public class Vala.Property : CodeNode { } public override void accept (CodeVisitor! visitor) { + visitor.visit_member (this); visitor.visit_begin_property (this); type_reference.accept (visitor); @@ -151,4 +154,12 @@ public class Vala.Property : CodeNode { } } } + + public override bool get_lock_used () { + return lock_used; + } + + public override void set_lock_used (bool used) { + lock_used = used; + } } diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index b43f098..a22897a 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -36,6 +36,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { Symbol current_symbol; SourceFile current_source_file; TypeReference current_return_type; + Class current_class; List current_using_directives; @@ -99,6 +100,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { public override void visit_begin_class (Class! cl) { current_symbol = cl.symbol; + current_class = cl; if (cl.base_class != null) { current_source_file.add_symbol_dependency (cl.base_class.symbol, SourceFileDependencyType.HEADER_FULL); @@ -115,11 +117,21 @@ public class Vala.SemanticAnalyzer : CodeVisitor { public override void visit_begin_struct (Struct! st) { current_symbol = st.symbol; + current_class = null; } public override void visit_end_struct (Struct! st) { current_symbol = current_symbol.parent_symbol; } + + public override void visit_constant (Constant! c) { + if (!current_source_file.pkg) { + if (c.initializer == null) { + c.error = true; + Report.error (c.source_reference, "A const field requires a initializer to be provided"); + } + } + } public override void visit_field (Field! f) { if (f.access != MemberAccessibility.PRIVATE) { @@ -548,6 +560,30 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } } + /** + * Visit operation called for lock statements. + * + * @param stmt a lock statement + */ + public override void visit_lock_statement (LockStatement! stmt) { + /* resource must be a member access and denote a Lockable */ + if (!(stmt.resource is MemberAccess && stmt.resource.symbol_reference.node is Lockable)) { + stmt.error = true; + stmt.resource.error = true; + Report.error (stmt.resource.source_reference, "Expression is either not a member access or does not denote a lockable member"); + return; + } + + /* parent symbol must be the current class */ + if (stmt.resource.symbol_reference.parent_symbol.node != current_class) { + stmt.error = true; + stmt.resource.error = true; + Report.error (stmt.resource.source_reference, "Only members of the current class are lockable"); + } + + ((Lockable)stmt.resource.symbol_reference.node).set_lock_used (true); + } + public override void visit_begin_array_creation_expression (ArrayCreationExpression! expr) { if (expr.initializer_list != null) { expr.initializer_list.expected_type = expr.element_type.copy (); diff --git a/vala/vala/valasignal.vala b/vala/vala/valasignal.vala index d1b260a..93c4564 100644 --- a/vala/vala/valasignal.vala +++ b/vala/vala/valasignal.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents an object signal. Signals enable objects to provide notifications. */ -public class Vala.Signal : CodeNode, Invokable { +public class Vala.Signal : Member, Invokable, Lockable { /** * The symbol name of this signal. */ @@ -51,6 +51,8 @@ public class Vala.Signal : CodeNode, Invokable { private Callback generated_callback; private string cname; + + private bool lock_used = false; /** * Creates a new signal. @@ -153,6 +155,8 @@ public class Vala.Signal : CodeNode, Invokable { } public override void accept (CodeVisitor! visitor) { + visitor.visit_member (this); + visitor.visit_begin_signal (this); return_type.accept (visitor); @@ -174,4 +178,12 @@ public class Vala.Signal : CodeNode, Invokable { } } } + + public override bool get_lock_used () { + return lock_used; + } + + public override void set_lock_used (bool used) { + lock_used = used; + } } diff --git a/vala/vapi/glib-2.0.vala b/vala/vapi/glib-2.0.vala index fccb07b..379e837 100644 --- a/vala/vapi/glib-2.0.vala +++ b/vala/vapi/glib-2.0.vala @@ -1,6 +1,6 @@ /* glib-2.0.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006 Jürg Billeter, Raffaele Sandrini * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,6 +18,7 @@ * * Author: * Jürg Billeter + * Raffaele Sandrini */ [CCode (cname = "gboolean", cheader_filename = "glib.h", type_id = "G_TYPE_BOOLEAN", marshaller_type_name = "BOOLEAN")] @@ -359,19 +360,55 @@ namespace GLib { public callback bool SourceFunc (pointer data); + /* Thread support */ [ReferenceType ()] public struct ThreadFunctions { } + public callback pointer ThreadFunc (pointer data); + public callback void Func (pointer data, pointer user_data); + + public enum ThreadPriority { + LOW, + NORMAL, + HIGH, + URGENT + } + [ReferenceType ()] public struct Thread { - public static void init (ThreadFunctions vtable); + public static void init (ThreadFunctions vtable = null); public static bool supported (); + public static ref Thread create (ThreadFunc func, pointer data, bool joinable, out Error error); + public static ref Thread create_full (ThreadFunc func, pointer data, ulong stack_size, bool joinable, bool bound, ThreadPriority priority, out Error error); + public static ref Thread self (); + public pointer join (); + public void set_priority (ThreadPriority priority); + public static void yield (); + public static void exit (pointer retval); + public static void @foreach (Func thread_func, pointer user_data); [CCode (cname = "g_usleep")] public static void usleep (ulong microseconds); } + [ReferenceType (free_function = "g_mutex_free")] + public struct Mutex { + public construct (); + public void @lock (); + public bool try_lock (); + public void unlock (); + } + + [ReferenceType (free_function = "g_cond_free")] + public struct Cond { + public construct (); + public void @signal (); + public void broadcast (); + public void wait (Mutex mutex); + public bool timed_wait (Mutex mutex, TimeVal abs_time); + } + public static pointer malloc0 (ulong n_bytes); [ReferenceType ()] @@ -398,7 +435,15 @@ namespace GLib { public static ref string decode (string! text, ref ulong out_len); } + [ReferenceType (free_function = "g_free")] public struct TimeVal { + [CCode (cname = "g_get_current_time")] + public void get_current_time (); + public void add (long microseconds); + [InstanceLast ()] + public bool from_iso8601 (string iso_date); + public string to_iso8601 (); + } public struct Environment { -- 2.7.4