root/trunk/ProjectFortress/src/com/sun/fortress/interpreter/env/ReferenceCell.java @ 2738

Revision 2738, 7.5 KB (checked in by chf, 15 months ago)

Some cleanups and refactorings. More to come

Line 
1 /*******************************************************************************
2    Copyright 2008 Sun Microsystems, Inc.,
3    4150 Network Circle, Santa Clara, California 95054, U.S.A.
4    All rights reserved.
5
6    U.S. Government Rights - Commercial software.
7    Government users are subject to the Sun Microsystems, Inc. standard
8    license agreement and applicable provisions of the FAR and its supplements.
9
10    Use is subject to license terms.
11
12    This distribution may include materials developed by third parties.
13
14    Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
15    trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
16******************************************************************************/
17
18package com.sun.fortress.interpreter.env;
19
20import static com.sun.fortress.exceptions.InterpreterBug.bug;
21import com.sun.fortress.exceptions.transactions.AbortedException;
22import com.sun.fortress.exceptions.transactions.PanicException;
23import com.sun.fortress.interpreter.evaluator.tasks.FortressTaskRunner;
24import com.sun.fortress.interpreter.evaluator.transactions.Transaction;
25
26import java.util.concurrent.atomic.AtomicInteger;
27
28import com.sun.fortress.interpreter.evaluator.types.FType;
29import com.sun.fortress.interpreter.evaluator.values.FValue;
30
31/**
32 * What the interpreter stores mutable things (fields, variables)
33 * in.  It will eventually acquire transactional semantics.
34 */
35
36public class ReferenceCell extends IndirectionCell {
37    private FType theType;
38    ValueNode node;
39
40    // for debugging
41    static final AtomicInteger counter = new AtomicInteger(0);
42    final int id;
43
44    public ReferenceCell() {
45        super();
46        node = ValueNode.nullValueNode;
47        id = counter.getAndIncrement();
48    }
49
50    public ReferenceCell(FType t) {
51        super();
52        theType = t;
53        node = ValueNode.nullValueNode;
54        id = counter.getAndIncrement();
55    }
56
57    public ReferenceCell(FType t, FValue v) {
58        super();
59        theType = t;
60        node = new ValueNode(v, FortressTaskRunner.getTransaction(), null, null);
61        id = counter.getAndIncrement();
62    }
63
64    public FType getType() { return theType;}
65    public String toString() { return "ReferenceCell" + id;}
66
67    private boolean transactionIsCommitted(Transaction w) {
68        if (w == null) return true;
69        else if (w.isCommitted()) return true;
70        return false;
71    }
72
73    private boolean transactionIsAbortedOrOrphaned(Transaction w) {
74        if (w == null) return false;
75        else if (w.isAborted()) return true;
76        else if (w.isOrphaned()) return true;
77        else return false;
78        }
79
80    private boolean transactionIsNotActive(Transaction w) {
81        if (w == null) return false;
82        else if (w.isAborted()) return true;
83        else if (w.isOrphaned()) return true;
84        else if (w.isCommitted()) return true;
85        else return false;
86    }
87
88
89    private synchronized void cleanup() {
90        Transaction w = node.getWriter();
91        if (Transaction.debug)
92            FortressTaskRunner.debugPrintln("Cleanup:" + this + " start with node = " + node);
93        while (w != null && transactionIsNotActive(w)) {
94            if (transactionIsAbortedOrOrphaned(w)) {
95                node = node.getOld();
96            } else {
97                assert(transactionIsCommitted(w));
98                Transaction p = w.getParent();
99                ValueNode old = node.getOld();
100                if (p == null && old == null) {
101                    // Committed to top level, with no previous value.
102                    node = new ValueNode(node.getValue(), null, null, null);
103                } else if (p == null) {
104                    // Committed to top level.  Any readers of the committed transaction
105                    // must be preserved.
106                    node = new ValueNode(node.getValue(), null, old.getReaders(), null);
107                } else  if (old != null) {
108                    // Committed to a parent transaction, must preserve readers and
109                    // old transaction.
110                    node = new ValueNode(node.getValue(), p, old.getReaders(), old);
111                } else {
112                    node = new ValueNode(node.getValue(), p, null, null);
113                }
114            }
115            if (node != null) {
116                w = node.getWriter();
117            } else {
118                node = ValueNode.nullValueNode;
119                if (Transaction.debug)
120                    FortressTaskRunner.debugPrintln("Cleanup:" + this + " end with " + node);
121                return;
122            }
123        }
124        if (Transaction.debug)
125            FortressTaskRunner.debugPrintln("Cleanup:" + this + " end with " + node);
126    }
127
128    public synchronized void assignValue(FValue f2) {
129        Transaction me  = FortressTaskRunner.getTransaction();
130        cleanup();
131        if (Transaction.debug)
132            FortressTaskRunner.debugPrintln(this + " assignValue start = " + node + " value = " + f2);
133
134        if (node == ValueNode.nullValueNode) {
135            node = new ValueNode(f2, me, null, null);
136        }
137
138        // writer is either active, or null
139        if (me == null) { // top level assignment
140            if (node == ValueNode.nullValueNode)
141                node = new ValueNode(f2, me, null, null);
142            else {
143                ValueNode temp = node;
144                node = new ValueNode(f2, null, null, null);
145                temp.AbortAllReadersAndWriters();
146            }
147        } else if (!me.isActive()) {
148            throw new AbortedException(me, "Somebody killed me ");
149        } else {
150            node.resolveReadWriteConflicts();
151            cleanup();
152            if (!me.isActive())
153                throw new AbortedException(me, "Somebody killed me ");     
154
155            Transaction w = node.getWriter();
156            ValueNode old = node.getOld();
157
158            if (w == null || w.isAncestorOf(me)) {
159                node = new ValueNode(f2, me, node.getReaders(), node);
160                if (Transaction.debug) me.addWrite(this, f2);
161
162            } else if (w.isActive()) {
163                                // Cleanup got us to a parent node with an active writer
164                assignValue(f2);
165            }
166        }
167        if (Transaction.debug)
168            FortressTaskRunner.debugPrintln(this + " assignValue finish = " + node);
169    }
170
171    public synchronized FValue getValue() {
172        Transaction me  = FortressTaskRunner.getTransaction();
173        // Top Level transaction
174        if (me == null) {
175                        while (node.getWriter() != null) {
176                                node.AbortWriter();
177                                cleanup();
178                        }
179            return node.getValue();
180        }
181
182        if (!me.isActive()) throw new AbortedException(me, "Somebody killed me");   
183
184        cleanup(); 
185
186        Transaction w = node.getWriter();
187        if (w == me) {
188            return node.getValue();
189        } else if (w == null || w.isAncestorOf(me)) {
190            node.addReader();
191            if (Transaction.debug) me.addRead(this, node.getValue());
192            return node.getValue();
193        } else if (w.isActive()) {     
194            node.resolveWriteConflict();
195        }
196        return getValue();
197    }
198
199    public FValue getValueNull() {
200        return getValue();
201    }
202
203
204    public void storeValue(FValue f2) {
205        if (node.getValue() != null)
206            bug("Internal error, second store of indirection cell");
207        assignValue(f2);
208    }
209
210    public void storeType(FType f2) {
211        if (theType != null)
212            bug("Internal error, second store of type");
213        theType = f2;
214    }
215   
216    public boolean isInitialized() {
217        return getValue() != null;
218    }
219
220}
Note: See TracBrowser for help on using the browser.