add threading and assorted structures add an additional abstraction for
authorRaffaele Sandrini <rasa@gmx.ch>
Wed, 27 Sep 2006 12:37:03 +0000 (12:37 +0000)
committerRaffaele Sandrini <rasa@src.gnome.org>
Wed, 27 Sep 2006 12:37:03 +0000 (12:37 +0000)
2006-09-27  Raffaele Sandrini  <rasa@gmx.ch>

* 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

17 files changed:
vala/ChangeLog
vala/vala/Makefile.am
vala/vala/parser.y
vala/vala/scanner.l
vala/vala/vala.h
vala/vala/valacodegenerator.vala
vala/vala/valacodevisitor.vala
vala/vala/valaconstant.vala
vala/vala/valafield.vala
vala/vala/valalockable.vala [new file with mode: 0644]
vala/vala/valalockstatement.vala [new file with mode: 0644]
vala/vala/valamember.vala [new file with mode: 0644]
vala/vala/valamethod.vala
vala/vala/valaproperty.vala
vala/vala/valasemanticanalyzer.vala
vala/vala/valasignal.vala
vala/vapi/glib-2.0.vala

index 54d913e..8320f94 100644 (file)
@@ -1,3 +1,22 @@
+2006-09-27  Raffaele Sandrini  <rasa@gmx.ch>
+
+       * 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  <j@bitron.ch>
 
        * vapi/glib-2.0.vala: add Process struct with spawn functions
index 8ec3b25..6f31e97 100644 (file)
@@ -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 \
index 6af4151..41ae4fb 100644 (file)
@@ -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 <statement> break_statement
 %type <statement> continue_statement
 %type <statement> return_statement
+%type <statement> lock_statement
 %type <namespace> namespace_declaration
 %type <str> opt_name_specifier
 %type <str> 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
          {
index e6c17ea..cf147b7 100644 (file)
@@ -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; }
index 4dc05e1..7177791 100644 (file)
@@ -1,3 +1,4 @@
+#include <vala/valaarraycreationexpression.h>
 #include <vala/valaassignment.h>
 #include <vala/valaattribute.h>
 #include <vala/valabinaryexpression.h>
@@ -36,6 +37,7 @@
 #include <vala/valaliteral.h>
 #include <vala/valaliteralexpression.h>
 #include <vala/valalocalvariabledeclaration.h>
+#include <vala/valalockstatement.h>
 #include <vala/valamemberaccess.h>
 #include <vala/valamethod.h>
 #include <vala/valanamedargument.h>
@@ -65,4 +67,3 @@
 #include <vala/valaunaryexpression.h>
 #include <vala/valavariabledeclarator.h>
 #include <vala/valawhilestatement.h>
-#include <vala/valaarraycreationexpression.h>
index 4598e52..f6d60ec 100644 (file)
@@ -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.
         *
index c88c754..6cc9529 100644 (file)
@@ -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
index 08ae73d..e69c578 100644 (file)
@@ -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;
+       }
 }
index 7612f49..f8c71a4 100644 (file)
@@ -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 (file)
index 0000000..69bcae5
--- /dev/null
@@ -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 <rasa@gmx.ch>
+ */
+
+/**
+ * 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 (file)
index 0000000..2fc537a
--- /dev/null
@@ -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 <rasa@gmx.ch>
+ */
+
+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 (file)
index 0000000..651a98b
--- /dev/null
@@ -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 <rasa@gmx.ch>
+ */
+
+/**
+ * Represents a general class member.
+ */
+public class Vala.Member : CodeNode {
+       public override void accept (CodeVisitor! visitor) {
+               visitor.visit_member (this);
+       }
+}
index 9ff7ae2..ffd7f01 100644 (file)
@@ -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.
         */
index 69c2887..da3fe98 100644 (file)
@@ -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;
+       }
 }
index b43f098..a22897a 100644 (file)
@@ -36,6 +36,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        Symbol current_symbol;
        SourceFile current_source_file;
        TypeReference current_return_type;
+       Class current_class;
        
        List<weak NamespaceReference> 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 ();
index d1b260a..93c4564 100644 (file)
@@ -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;
+       }
 }
index fccb07b..379e837 100644 (file)
@@ -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 <j@bitron.ch>
+ *     Raffaele Sandrini <rasa@gmx.ch>
  */
 
 [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 {