| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | package com.sun.fortress.interpreter.env; |
|---|
| 19 | |
|---|
| 20 | import static com.sun.fortress.exceptions.InterpreterBug.bug; |
|---|
| 21 | import com.sun.fortress.exceptions.transactions.AbortedException; |
|---|
| 22 | import com.sun.fortress.exceptions.transactions.PanicException; |
|---|
| 23 | import com.sun.fortress.interpreter.evaluator.tasks.FortressTaskRunner; |
|---|
| 24 | import com.sun.fortress.interpreter.evaluator.transactions.Transaction; |
|---|
| 25 | |
|---|
| 26 | import java.util.concurrent.atomic.AtomicInteger; |
|---|
| 27 | |
|---|
| 28 | import com.sun.fortress.interpreter.evaluator.types.FType; |
|---|
| 29 | import com.sun.fortress.interpreter.evaluator.values.FValue; |
|---|
| 30 | |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | |
|---|
| 34 | |
|---|
| 35 | |
|---|
| 36 | public class ReferenceCell extends IndirectionCell { |
|---|
| 37 | private FType theType; |
|---|
| 38 | ValueNode node; |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | static final AtomicInteger counter = new AtomicInteger(0); |
|---|
| 42 | final int id; |
|---|
| 43 | |
|---|
| 44 | public ReferenceCell() { |
|---|
| 45 | super(); |
|---|
| 46 | node = new ValueNode(); |
|---|
| 47 | id = counter.getAndIncrement(); |
|---|
| 48 | } |
|---|
| 49 | |
|---|
| 50 | public ReferenceCell(FType t, FValue v) { |
|---|
| 51 | super(); |
|---|
| 52 | theType = t; |
|---|
| 53 | node = new ValueNode(v); |
|---|
| 54 | id = counter.getAndIncrement(); |
|---|
| 55 | } |
|---|
| 56 | |
|---|
| 57 | public ReferenceCell(FType t) { |
|---|
| 58 | super(); |
|---|
| 59 | theType = t; |
|---|
| 60 | node = new ValueNode(); |
|---|
| 61 | id = counter.getAndIncrement(); |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | public FType getType() { return theType;} |
|---|
| 65 | public String toString() { return "ReferenceCell" + id;} |
|---|
| 66 | |
|---|
| 67 | |
|---|
| 68 | private boolean transactionIsCommitted(Transaction w) { |
|---|
| 69 | if (w == null) return true; |
|---|
| 70 | else if (w.isCommitted()) return true; |
|---|
| 71 | return false; |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | private boolean transactionIsAbortedOrOrphaned(Transaction w) { |
|---|
| 75 | if (w == null) return false; |
|---|
| 76 | else if (w.isAborted()) return true; |
|---|
| 77 | else if (w.isOrphaned()) return true; |
|---|
| 78 | else return false; |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | private boolean transactionIsNotActive(Transaction w) { |
|---|
| 82 | if (w == null) return false; |
|---|
| 83 | else if (w.isAborted()) return true; |
|---|
| 84 | else if (w.isOrphaned()) return true; |
|---|
| 85 | else if (w.isCommitted()) return true; |
|---|
| 86 | else return false; |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | private synchronized void cleanup() { |
|---|
| 91 | Transaction w = node.getWriter(); |
|---|
| 92 | while (w != null && transactionIsNotActive(w)) { |
|---|
| 93 | if (transactionIsAbortedOrOrphaned(w)) { |
|---|
| 94 | node = node.getOld(); |
|---|
| 95 | } else { |
|---|
| 96 | assert(transactionIsCommitted(w)); |
|---|
| 97 | Transaction p = w.getParent(); |
|---|
| 98 | if (p == null) { |
|---|
| 99 | node = new ValueNode(node.getValue(), node.getOld().getReaders()); |
|---|
| 100 | } else { |
|---|
| 101 | node = new ValueNode(node.getValue(), p, node.getOld()); |
|---|
| 102 | } |
|---|
| 103 | } |
|---|
| 104 | if (node != null) { |
|---|
| 105 | w = node.getWriter(); |
|---|
| 106 | } else { |
|---|
| 107 | node = new ValueNode(); |
|---|
| 108 | return; |
|---|
| 109 | } |
|---|
| 110 | } |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | public synchronized void assignValue(FValue f2) { |
|---|
| 114 | Transaction me = FortressTaskRunner.getTransaction(); |
|---|
| 115 | cleanup(); |
|---|
| 116 | |
|---|
| 117 | if (me == null) { |
|---|
| 118 | ValueNode temp = node; |
|---|
| 119 | node = new ValueNode(f2); |
|---|
| 120 | temp.AbortAllReadersAndWriters(); |
|---|
| 121 | } else if (!me.isActive()) { |
|---|
| 122 | throw new AbortedException(me, "Somebody killed me "); |
|---|
| 123 | } else { |
|---|
| 124 | node.resolveReadWriteConflicts(); |
|---|
| 125 | cleanup(); |
|---|
| 126 | if (!me.isActive()) |
|---|
| 127 | throw new AbortedException(me, "Somebody killed me "); |
|---|
| 128 | |
|---|
| 129 | Transaction w = node.getWriter(); |
|---|
| 130 | |
|---|
| 131 | if (w == null || w.isAncestorOf(me)) { |
|---|
| 132 | node = new ValueNode(f2, me, node); |
|---|
| 133 | if (Transaction.debug) me.addWrite(this, f2); |
|---|
| 134 | } else if (w.isActive()) { |
|---|
| 135 | |
|---|
| 136 | assignValue(f2); |
|---|
| 137 | } |
|---|
| 138 | } |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | public synchronized FValue getValue() { |
|---|
| 142 | Transaction me = FortressTaskRunner.getTransaction(); |
|---|
| 143 | |
|---|
| 144 | if (me == null) { |
|---|
| 145 | while (node.getWriter() != null) { |
|---|
| 146 | node.AbortWriter(); |
|---|
| 147 | cleanup(); |
|---|
| 148 | } |
|---|
| 149 | return node.getValue(); |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | if (!me.isActive()) throw new AbortedException(me, "Somebody killed me"); |
|---|
| 153 | |
|---|
| 154 | cleanup(); |
|---|
| 155 | |
|---|
| 156 | Transaction w = node.getWriter(); |
|---|
| 157 | if (w == me) { |
|---|
| 158 | return node.getValue(); |
|---|
| 159 | } else if (w == null || w.isAncestorOf(me)) { |
|---|
| 160 | node.addReader(); |
|---|
| 161 | if (Transaction.debug) me.addRead(this, node.getValue()); |
|---|
| 162 | return node.getValue(); |
|---|
| 163 | } else if (w.isActive()) { |
|---|
| 164 | node.resolveWriteConflict(); |
|---|
| 165 | } |
|---|
| 166 | return getValue(); |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | public FValue getValueNull() { |
|---|
| 170 | return getValue(); |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | |
|---|
| 174 | public void storeValue(FValue f2) { |
|---|
| 175 | if (node.getValue() != null) |
|---|
| 176 | bug("Internal error, second store of indirection cell"); |
|---|
| 177 | assignValue(f2); |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | public void storeType(FType f2) { |
|---|
| 181 | if (theType != null) |
|---|
| 182 | bug("Internal error, second store of type"); |
|---|
| 183 | theType = f2; |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | public boolean isInitialized() { |
|---|
| 187 | return getValue() != null; |
|---|
| 188 | } |
|---|
| 189 | |
|---|
| 190 | } |
|---|