1 /* valalockstatement.vala
3 * Copyright (C) 2009 Jiří Zárevúcky
4 * Copyright (C) 2006-2010 Jürg Billeter
5 * Copyright (C) 2006-2007 Raffaele Sandrini
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Raffaele Sandrini <raffaele@sandrini.ch>
23 * Jiří Zárevúcky <zarevucky.jiri@gmail.com>
29 * Represents a lock statement e.g. {{{ lock (a); }}} or {{{ lock (a) { f(a); } }}}.
31 * If the statement is empty, the mutex remains locked until a corresponding UnlockStatement
32 * occurs. Otherwise it's translated into a try/finally statement which unlocks the mutex
33 * after the block is finished.
35 public class Vala
.LockStatement
: CodeNode
, Statement
{
37 * Expression representing the resource to be locked.
39 public Expression resource
{ get; set; }
42 * The statement during its execution the resource is locked.
44 public Block? body
{ get; set; }
46 public LockStatement (Expression resource
, Block? body
, SourceReference? source_reference
= null) {
48 this
.source_reference
= source_reference
;
49 this
.resource
= resource
;
52 public override void accept (CodeVisitor visitor
) {
53 resource
.accept (visitor
);
55 body
.accept (visitor
);
57 visitor
.visit_lock_statement (this
);
60 public override bool check (CodeContext context
) {
62 // if the statement isn't empty, it is converted into a try statement
64 var fin_body
= new
Block (source_reference
);
65 fin_body
.add_statement (new
UnlockStatement (resource
, source_reference
));
67 var block
= new
Block (source_reference
);
68 block
.add_statement (new
LockStatement (resource
, null, source_reference
));
69 block
.add_statement (new
TryStatement (body
, fin_body
, source_reference
));
71 var parent_block
= (Block
) parent_node
;
72 parent_block
.replace_statement (this
, block
);
74 return block
.check (context
);
83 resource
.check (context
);
85 /* resource must be a member access and denote a Lockable */
86 if (!(resource is MemberAccess
&& resource
.symbol_reference is Lockable
)) {
88 resource
.error
= true;
89 Report
.error (resource
.source_reference
, "Expression is either not a member access or does not denote a lockable member");
93 /* parent symbol must be the current class */
94 if (resource
.symbol_reference
.parent_symbol
!= context
.analyzer
.current_class
) {
96 resource
.error
= true;
97 Report
.error (resource
.source_reference
, "Only members of the current class are lockable");
100 ((Lockable
) resource
.symbol_reference
).lock_used
= true;
105 public override void emit (CodeGenerator codegen
) {
106 resource
.emit (codegen
);
107 codegen
.visit_lock_statement (this
);